Compare commits

...

368 Commits

Author SHA1 Message Date
036e1dd82d Merge branch 'main' of http://10.10.1.136:3000/ismail/haikal into main 2025-03-13 23:59:39 +03:00
b955ce4aa3 o 2025-03-13 23:57:14 +03:00
68fb46cf65 add ledger and journalentry 2025-03-11 21:36:19 +00:00
55167f2cc1 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-03-07 00:37:23 +00:00
bada43ba64 change 2025-03-07 00:23:02 +00:00
Marwan Alwali
6af5249454 update 2025-03-06 23:27:04 +03:00
Marwan Alwali
7dd5791d14 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	inventory/views.py
2025-03-05 02:35:37 +03:00
Marwan Alwali
b54634b2a1 update 2025-03-05 02:35:00 +03:00
540f9cbe3c update1 2025-03-04 23:24:29 +00:00
76fbb4a69b fix conflict issue 2025-03-04 21:50:29 +00:00
4cd61f6a84 temp 2025-03-04 21:25:33 +00:00
c5ba624585 p 2025-03-04 21:21:03 +00:00
034d0a9501 update 2025-03-04 21:14:47 +00:00
c11fc359bd add permissions 2025-03-04 21:13:23 +00:00
Marwan Alwali
31fa1b8011 update 2025-03-04 21:55:50 +03:00
Marwan Alwali
9c55bdbe92 update 2025-03-04 00:03:29 +03:00
Marwan Alwali
1580e2ad26 update 2025-03-02 21:21:15 +03:00
a96b1131d3 update customer and organization & staffmember 2025-03-02 12:18:32 +00:00
21089f8995 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-27 16:16:07 +00:00
cf89b54df1 update 2025-02-27 16:16:03 +00:00
Marwan Alwali
a7987c283b update 2025-02-27 18:56:59 +03:00
1a98cfc7bc Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-27 15:02:46 +00:00
86d3c3d586 update 2025-02-27 15:02:41 +00:00
Marwan Alwali
00c07b5442 update 2025-02-27 15:01:32 +03:00
91ef0da13b update 2025-02-26 16:01:58 +00:00
12d480659e update 2025-02-26 13:01:22 +00:00
0ecbee79f2 update 2025-02-26 12:26:30 +00:00
219a3e9426 update 2025-02-26 12:25:46 +00:00
Marwan Alwali
9e54207395 update 2025-02-26 15:23:38 +03:00
Marwan Alwali
218fea7a26 update 2025-02-26 13:32:26 +03:00
Marwan Alwali
f3cd624851 update 2025-02-25 14:43:25 +03:00
a266c99028 update 2025-02-24 14:51:46 +00:00
2557ac12c5 update 2025-02-24 14:50:52 +00:00
8714162a58 update 2025-02-24 14:50:13 +00:00
Marwan Alwali
2671db939a update 2025-02-24 14:35:10 +03:00
8ae17c9560 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-24 11:31:26 +00:00
bc77e6c79d changes 2025-02-24 11:31:24 +00:00
Marwan Alwali
27530ab096 update 2025-02-23 22:12:16 +03:00
Marwan Alwali
3458671826 update 2025-02-23 13:17:11 +03:00
Marwan Alwali
5ce971b4bd update 2025-02-20 17:46:28 +03:00
6e598dfce5 update 2025-02-20 14:43:45 +00:00
475518c37e Merge branch 'user_group' 2025-02-20 14:19:07 +00:00
68652d17e5 update 2025-02-20 14:18:39 +00:00
ddc13aadab update 2025-02-20 11:18:47 +00:00
Marwan Alwali
6419070c86 update 2025-02-20 13:52:24 +03:00
1bd663446b update the perms 2025-02-20 10:30:10 +00:00
Marwan Alwali
ed3e79e35f update 2025-02-20 11:41:44 +03:00
fe0f0d836d update 2025-02-19 13:56:19 +00:00
Marwan Alwali
7d93bfde9f update 2025-02-19 07:46:29 +03:00
d937f9f684 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-18 13:32:56 +00:00
87cac68e8b update on the appointment and lead and more 2025-02-18 13:32:40 +00:00
Marwan Alwali
f72f3ff9d1 update 2025-02-18 12:10:51 +03:00
491d60b34f update 2025-02-18 08:29:08 +00:00
Marwan Alwali
7423fa9878 update 2025-02-18 09:57:19 +03:00
Marwan Alwali
9b282154b0 update 2025-02-17 21:46:27 +03:00
3e2af239e4 update 2025-02-17 16:13:28 +00:00
d20192e28d update 2025-02-17 12:26:08 +00:00
2a8e584f30 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-17 12:09:39 +00:00
80f0d40850 update 2025-02-17 12:09:37 +00:00
Marwan Alwali
96e3d3af01 update 2025-02-17 15:06:46 +03:00
692ee44504 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-17 11:21:00 +00:00
e34109fd3e add history + some fixes 2025-02-17 11:20:55 +00:00
Marwan Alwali
c559e5d3d5 update 2025-02-17 12:27:15 +03:00
Marwan Alwali
7a116cbaba Merge remote-tracking branch 'origin/main' 2025-02-16 18:37:15 +03:00
Marwan Alwali
5a821fa073 update 2025-02-16 18:37:09 +03:00
9b9edbefa8 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-16 15:35:09 +00:00
6a52b717d5 update 2025-02-16 15:33:11 +00:00
Marwan Alwali
bb1fac8609 update 2025-02-16 18:12:13 +03:00
Marwan Alwali
ec6ca7dfd7 update 2025-02-16 12:56:14 +03:00
Marwan Alwali
813f014c46 update 2025-02-16 12:40:10 +03:00
Marwan Alwali
692fa3f0ed update 2025-02-16 11:48:12 +03:00
Marwan Alwali
dbf4c6f91d update 2025-02-13 18:19:55 +03:00
f777cea2bb update 2025-02-13 15:10:25 +00:00
Marwan Alwali
4b5ad23869 Merge remote-tracking branch 'origin/main' 2025-02-13 17:26:09 +03:00
Marwan Alwali
fb80514fa6 update 2025-02-13 17:25:57 +03:00
bb9630cc33 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-13 14:21:22 +00:00
771390045b update 2025-02-13 14:21:18 +00:00
Marwan Alwali
7144caecec update 2025-02-13 14:14:56 +03:00
631da4d9b6 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-13 08:49:53 +00:00
8cd795c237 update 2025-02-13 08:49:51 +00:00
Marwan Alwali
709b3359f3 update 2025-02-13 11:11:32 +03:00
Marwan Alwali
0733ea3669 update 2025-02-12 20:04:22 +03:00
Marwan Alwali
41e1a7d472 update 2025-02-12 18:26:04 +03:00
266bd54fe3 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-12 15:23:44 +00:00
040e26b3f9 update in opportunity 2025-02-12 15:23:40 +00:00
Marwan Alwali
6694f889ea update 2025-02-12 12:12:07 +03:00
93674f646b Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-11 14:20:04 +00:00
387b7b099c add sales list 2025-02-11 14:19:51 +00:00
Marwan Alwali
ec30867916 update 2025-02-11 15:17:42 +03:00
c37f87299b Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-11 12:16:14 +00:00
a2ffd67e75 add filter in car list 2025-02-11 12:16:11 +00:00
Marwan Alwali
f610309026 update 2025-02-10 20:40:39 +03:00
Marwan Alwali
74c63633ed update 2025-02-10 17:45:35 +03:00
Marwan Alwali
214f0fbd21 Merge remote-tracking branch 'origin/main' 2025-02-10 17:33:03 +03:00
Marwan Alwali
727ec76f19 update 2025-02-10 17:31:37 +03:00
9682cd0f01 add car list view 2025-02-10 14:30:06 +00:00
dff5148028 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-10 14:26:54 +00:00
8d19c15f73 add car list view 2025-02-10 14:26:32 +00:00
Marwan Alwali
53d7db0bfc update 2025-02-10 14:42:07 +03:00
Marwan Alwali
7379bb9e4d Merge remote-tracking branch 'origin/main' 2025-02-09 20:25:37 +03:00
Marwan Alwali
d6cee4f99c update 2025-02-09 20:17:40 +03:00
Marwan Alwali
fef20c666d update 2025-02-09 20:17:22 +03:00
f4111803bb update 2025-02-09 16:19:52 +00:00
ffd72e2d93 changes 2025-02-09 07:38:44 +00:00
778a41aa47 changes 2025-02-09 07:36:28 +00:00
Marwan Alwali
315589b669 update 2025-02-09 09:49:42 +03:00
Marwan Alwali
c4ea8db46e update 2025-02-08 11:50:06 +03:00
Marwan Alwali
48d70dc084 update 2025-02-07 06:46:12 +03:00
Marwan Alwali
1f2cf5a7ec update 2025-02-06 11:49:47 +03:00
Marwan Alwali
43df77dc7b update 2025-02-06 11:42:53 +03:00
Marwan Alwali
1aff58a708 update 2025-02-06 11:35:21 +03:00
333f4ce686 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-06 08:34:41 +00:00
df148e03ad update lead 2025-02-06 08:34:23 +00:00
Marwan Alwali
482fa0b3f3 update 2025-02-05 20:03:29 +03:00
Marwan Alwali
3febd59d86 update 2025-02-04 22:37:12 +03:00
Marwan Alwali
83138fc3ed update 2025-02-04 22:35:17 +03:00
5cff4678ad update lead 2025-02-04 16:12:13 +00:00
a49ace441f update 2025-02-03 15:27:53 +00:00
f8f33c0f58 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-02-03 15:23:20 +00:00
11d801f488 update bill 2025-02-03 15:23:06 +00:00
Marwan Alwali
ddd0be29c5 update 2025-02-03 11:56:59 +03:00
Marwan Alwali
4631aa48c7 update 2025-02-03 11:56:06 +03:00
8ede7e815d update 2025-02-03 08:54:57 +00:00
Marwan Alwali
7ff112a5ef update 2025-02-03 11:52:02 +03:00
48370d75c1 update 2025-02-03 08:51:26 +00:00
Marwan Alwali
6c328953e8 update 2025-02-02 18:23:00 +03:00
Marwan Alwali
e3122a4a29 update 2025-02-02 17:33:11 +03:00
Marwan Alwali
c92371a9b5 update 2025-02-02 17:22:35 +03:00
1c567427b2 update dashboard 2025-02-02 13:56:01 +00:00
564a724663 update dashboard 2025-02-02 13:53:37 +00:00
Marwan Alwali
a4433631fb update 2025-02-02 11:04:08 +03:00
Marwan Alwali
e3c1810b4a update 2025-01-30 13:13:07 +03:00
Marwan Alwali
74e4bb1684 update 2025-01-30 13:11:17 +03:00
ecf1c375c1 latest update 2025-01-30 09:56:33 +00:00
Marwan Alwali
9cd5c454d2 update 2025-01-30 12:03:45 +03:00
Marwan Alwali
1dd4780085 update 2025-01-30 08:24:55 +03:00
Marwan Alwali
e3afa9d43f update 2025-01-28 15:36:17 +03:00
5ef0d68f7c after merge 2025-01-28 12:34:03 +00:00
a3cb3c5f55 update 2025-01-28 12:28:05 +00:00
Marwan Alwali
fe00d0d364 update 2025-01-28 15:27:11 +03:00
Marwan Alwali
0ea8d6a220 update 2025-01-27 20:40:32 +03:00
Marwan Alwali
af1b94baa8 update 2025-01-27 19:28:34 +03:00
Marwan Alwali
1ed04ec706 update 2025-01-27 19:24:42 +03:00
7142975004 sale order 2025-01-27 15:41:30 +00:00
Marwan Alwali
679c5ee2ca Merge remote-tracking branch 'origin/main' 2025-01-26 18:41:53 +03:00
Marwan Alwali
df8760ebe0 update 2025-01-26 18:24:33 +03:00
149c68cfae Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-01-26 15:11:30 +00:00
9a40e70ce3 update 2025-01-26 15:11:15 +00:00
Marwan Alwali
e2528f5ad7 update 2025-01-26 16:58:49 +03:00
Marwan Alwali
aaf12c950b update 2025-01-26 13:33:57 +03:00
Marwan Alwali
a7539819e6 update 2025-01-23 19:05:48 +03:00
Marwan Alwali
d53ce70f03 update 2025-01-22 17:32:39 +03:00
Marwan Alwali
37e6c589a8 update 2025-01-22 17:31:43 +03:00
c0d4a34c0d update 2025-01-22 14:31:09 +00:00
Marwan Alwali
6354f0c326 update 2025-01-22 16:20:54 +03:00
Marwan Alwali
e0bb0b4eda update 2025-01-22 16:05:25 +03:00
Marwan Alwali
8df5fbef8c update 2025-01-22 16:02:43 +03:00
Marwan Alwali
d675d50ae6 models.py 2025-01-22 15:47:56 +03:00
Marwan Alwali
25215db650 update 2025-01-22 15:35:54 +03:00
45a937a0b3 rebased 2025-01-22 12:34:08 +00:00
44c1f20801 update repo 2025-01-22 12:30:39 +00:00
aa975148db update repo 2025-01-22 12:25:52 +00:00
Marwan Alwali
752148e9ec update 2025-01-22 15:15:25 +03:00
Marwan Alwali
be3c86d00b update 2025-01-22 14:52:22 +03:00
3ebed60715 update 2025-01-22 11:50:02 +00:00
Marwan Alwali
19f01c2d95 update 2025-01-22 14:49:13 +03:00
Marwan Alwali
ca8e5a7190 update 2025-01-22 14:47:01 +03:00
Marwan Alwali
97c6f3f01a update 2025-01-22 14:44:23 +03:00
64f76c0f1a update in notifications and bills 2025-01-22 11:43:34 +00:00
042d1ac34b update 2025-01-21 13:11:12 +00:00
Marwan Alwali
e1ec1d8367 update 2025-01-21 15:56:15 +03:00
Marwan Alwali
5f55ffd74c update 2025-01-21 15:55:22 +03:00
43e1c7640f save 2025-01-21 12:09:22 +00:00
8e6e87a098 save 2025-01-21 12:04:02 +00:00
286265ac59 save 2025-01-21 11:55:04 +00:00
b2c609afa6 save 2025-01-21 11:50:46 +00:00
569fa3f7fb update 2025-01-21 11:44:12 +00:00
11e1a9d5e0 update 2025-01-21 11:35:58 +00:00
0e192d9c8b fix migrations issue 2025-01-21 08:57:21 +00:00
Marwan Alwali
6eb7d5bcd3 update 2025-01-20 18:45:25 +03:00
Marwan Alwali
662dc045c2 update 2025-01-20 18:41:12 +03:00
Marwan Alwali
8e7f8e8fec update 2025-01-20 18:33:43 +03:00
d0c37a9722 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-01-20 15:31:55 +00:00
6e3a2df75b add car transfer 2025-01-20 15:29:01 +00:00
Marwan Alwali
76989c6c1a update 2025-01-20 16:00:34 +03:00
Marwan Alwali
e7ca9d4de3 update 2025-01-20 15:57:32 +03:00
Marwan Alwali
62ebb56674 update 2025-01-19 19:11:15 +03:00
Marwan Alwali
c79b27148a update 2025-01-19 19:10:14 +03:00
8f50c142fc Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-01-19 11:24:26 +00:00
ffb560e565 add bills 2025-01-19 11:22:50 +00:00
Marwan Alwali
feeb882ee5 update 2025-01-19 11:14:29 +03:00
Marwan Alwali
01d0515b32 update 2025-01-18 17:07:15 +03:00
c277e73dec update 2025-01-16 17:31:44 +00:00
Marwan Alwali
99f0165603 update 2025-01-16 14:50:45 +03:00
Marwan Alwali
f84c07b8e3 update 2025-01-15 20:00:44 +03:00
Marwan Alwali
5442d5a539 update 2025-01-15 19:52:16 +03:00
9437fa10ce some changes 2025-01-15 13:30:36 +00:00
78ffb13703 some changes 2025-01-15 13:15:17 +00:00
a956e8485f some changes 2025-01-15 13:14:31 +00:00
e02ae8f010 fix the calculation and some small changes 2025-01-15 12:54:19 +00:00
Marwan Alwali
c69ebb8164 update 2025-01-15 13:28:57 +03:00
Marwan Alwali
6f82a87f95 update 2025-01-15 13:25:57 +03:00
03a4e6e498 changes 2025-01-15 10:16:56 +00:00
3608ee53d9 changes 2025-01-15 10:15:19 +00:00
Marwan Alwali
9a5339ba3c update 2025-01-15 13:07:25 +03:00
Marwan Alwali
704f0aaed6 update 2025-01-15 12:58:23 +03:00
28e051a061 update 2025-01-14 13:06:57 +00:00
0591e46755 some fixes 2025-01-14 12:11:32 +00:00
872cab6c04 change 2025-01-14 12:00:43 +00:00
b48d404655 update 2025-01-14 11:51:26 +00:00
Marwan Alwali
3889fed781 update 2025-01-13 21:40:17 +03:00
Marwan Alwali
1c668d3f0a update 2025-01-13 21:38:18 +03:00
2ed8ee24eb Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-01-13 08:17:25 +00:00
810900d76e update 2025-01-13 08:17:23 +00:00
Marwan Alwali
00f87799d0 update 2025-01-12 18:51:06 +03:00
Marwan Alwali
a03e909758 update 2025-01-12 18:25:19 +03:00
Marwan Alwali
5b48b3792a update 2025-01-12 18:07:28 +03:00
Marwan Alwali
e497f1083a update 2025-01-12 18:06:55 +03:00
9bb78d0723 update 2025-01-12 11:37:22 +00:00
Marwan Alwali
9549213a09 update 2025-01-12 09:33:42 +03:00
Marwan Alwali
c013f1683b update 2025-01-11 13:20:02 +03:00
Marwan Alwali
957d926675 update 2025-01-10 00:00:53 +03:00
Marwan Alwali
144d0434ad update 2025-01-09 23:55:29 +03:00
5400167008 add progress percent 2025-01-09 15:59:39 +00:00
48a9a8ffbb change 2025-01-09 15:36:00 +00:00
f6284d6690 update 2025-01-09 15:22:40 +00:00
9b82e53c86 added test + expenses + some changes 2025-01-09 15:21:23 +00:00
0c5948a253 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2025-01-09 15:17:02 +00:00
cc96947d18 added test + expenses + some changes 2025-01-09 15:16:50 +00:00
Marwan Alwali
3c9633100a update 2025-01-09 13:16:40 +03:00
Marwan Alwali
e84428263a update 2025-01-08 19:41:27 +03:00
9ccb432d19 additinal services, and estimate + invoice 2025-01-08 16:05:38 +00:00
Marwan Alwali
bb10d9186e update 2025-01-08 15:21:20 +03:00
Marwan Alwali
7fe829b362 update 2025-01-07 18:22:40 +03:00
Marwan Alwali
04c06dc45b update 2025-01-07 18:19:17 +03:00
521f43098f fix the invoice and estimate calculation 2025-01-07 15:02:35 +00:00
e1b2fb9c83 fix the invoice and estimate calculation 2025-01-07 14:35:36 +00:00
Marwan Alwali
66be7e2547 update 2025-01-07 16:52:24 +03:00
Marwan Alwali
43228b97a8 update 2025-01-07 16:45:00 +03:00
0cb378d25f update 2025-01-07 10:54:09 +00:00
Marwan Alwali
b8b388262a update 2025-01-06 21:55:48 +03:00
a03bb8ccf1 some changes in invoice 2025-01-06 15:51:19 +00:00
Marwan Alwali
f7a43a3b22 update 2025-01-06 17:42:06 +03:00
Marwan Alwali
047436c782 update 2025-01-06 17:41:23 +03:00
da1b53c775 fix the reserve when creating estimate 2025-01-06 14:40:14 +00:00
Marwan Alwali
0f9b2cff5f update 2025-01-06 15:59:11 +03:00
Marwan Alwali
48811b3d22 update 2025-01-06 15:58:05 +03:00
2399ac7dbc validate workflow 2025-01-06 12:57:15 +00:00
9ff796cf09 validate workflow 2025-01-06 12:34:19 +00:00
7ea259ccb9 cleanup 2025-01-06 08:05:24 +00:00
0b2eb83bf6 cleanup 2025-01-06 07:57:23 +00:00
Marwan Alwali
d772e1993c update 2025-01-05 16:08:50 +03:00
Marwan Alwali
d78643de95 update 2025-01-05 12:00:30 +03:00
Marwan Alwali
6c8168ca76 update 2025-01-05 11:59:34 +03:00
febfb03b56 update 2025-01-05 06:20:03 +00:00
Marwan Alwali
761cd2e338 update 2025-01-03 15:41:35 +03:00
Marwan Alwali
7cfd98528e update 2025-01-02 19:29:58 +03:00
Marwan Alwali
7b3688cb89 update 2025-01-02 19:17:06 +03:00
2eb86ea7e0 validations and more 2025-01-02 16:07:03 +00:00
Marwan Alwali
4664029c95 update 2025-01-01 19:19:33 +03:00
Marwan Alwali
ec05b88720 update 2025-01-01 19:01:53 +03:00
146fd26d52 update 2025-01-01 15:59:30 +00:00
0dd461d8cc update 2025-01-01 08:16:47 +00:00
2db2d8837c update 2025-01-01 07:53:56 +00:00
71fec40376 updaate 2025-01-01 07:51:11 +00:00
Marwan Alwali
c396960eaf update 2024-12-31 18:57:45 +03:00
Marwan Alwali
9b575dbc72 update 2024-12-31 18:54:24 +03:00
Marwan Alwali
970fbd08f2 update 2024-12-31 18:51:17 +03:00
7b167e5756 update 2024-12-31 15:44:49 +00:00
df4048e3a1 update 2024-12-31 15:40:09 +00:00
Marwan Alwali
3d1e78b4eb update 2024-12-31 14:16:06 +03:00
Marwan Alwali
8b00f9a40f update 2024-12-31 13:56:15 +03:00
Marwan Alwali
d29982d175 update 2024-12-30 20:25:05 +03:00
Marwan Alwali
8a6d0dc999 update 2024-12-30 18:08:54 +03:00
Marwan Alwali
b35a54b625 update 2024-12-30 18:08:05 +03:00
57b613032a add invoices 2024-12-30 15:06:21 +00:00
Marwan Alwali
7d3d9a6699 update 2024-12-30 16:18:39 +03:00
Marwan Alwali
8962646e2b update 2024-12-30 14:12:19 +03:00
2940819f84 update 2024-12-30 11:09:56 +00:00
6b5d39e069 update the estimate 2024-12-30 11:06:48 +00:00
Marwan Alwali
9879560ecb update 2024-12-30 14:04:44 +03:00
31c3fd98c8 update 2024-12-30 06:40:32 +00:00
aefa8a6881 update 2024-12-30 06:37:11 +00:00
Marwan Alwali
cced58632f update 2024-12-29 20:20:42 +03:00
Marwan Alwali
9d0485e1dd update 2024-12-29 17:56:22 +03:00
Marwan Alwali
40af920881 update 2024-12-29 17:55:24 +03:00
6ad4350183 estimate and bank accounts 2024-12-29 14:52:25 +00:00
239ebb8a65 estimate and bank accounts 2024-12-29 14:49:28 +00:00
Marwan Alwali
72091eac4e update 2024-12-29 17:19:16 +03:00
Marwan Alwali
b48d0600f4 update 2024-12-29 13:21:15 +03:00
Marwan Alwali
a24e5bc82b update 2024-12-26 19:07:08 +03:00
855c8f6c80 the dealer email issue not fixed 2024-12-26 16:02:42 +00:00
Marwan Alwali
794b2afeef update 2024-12-26 13:12:09 +03:00
Marwan Alwali
0eeb54d5d7 update 2024-12-26 13:08:09 +03:00
Marwan Alwali
b69c47b922 update 2024-12-26 13:06:54 +03:00
Marwan Alwali
38c1c5d44e update 2024-12-26 13:05:23 +03:00
c15d7dd696 Merge branch 'settingB' 2024-12-26 10:03:55 +00:00
56828d9a23 restore settings 2024-12-26 10:03:28 +00:00
98bac44df6 update 2024-12-26 09:50:28 +00:00
13074c5d94 update 2024-12-26 09:50:16 +00:00
Marwan Alwali
2456a806bc update 2024-12-26 12:47:44 +03:00
Marwan Alwali
23a311108d update 2024-12-26 12:47:07 +03:00
e834944dbc update 2024-12-26 09:46:37 +00:00
110d68aa87 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2024-12-26 09:38:51 +00:00
82ed9b20ac Merge branch 'new_branch' 2024-12-26 09:37:42 +00:00
Marwan Alwali
d03b19bb5a update 2024-12-26 12:32:16 +03:00
313eed6415 newudpate 2024-12-26 09:31:31 +00:00
Marwan Alwali
8ec1d14330 update 2024-12-26 11:10:47 +03:00
be055f2de7 update 2024-12-26 07:51:23 +00:00
Marwan Alwali
d15cb61a12 update 2024-12-25 20:35:05 +03:00
Marwan Alwali
1dc058396c update 2024-12-25 20:32:55 +03:00
71ad0bc9e6 update 2024-12-25 17:28:03 +00:00
c6a115576d Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2024-12-25 15:42:46 +00:00
Marwan Alwali
5ae1581b69 update 2024-12-25 18:41:29 +03:00
3a6d2408ff some updates 2024-12-25 15:33:36 +00:00
35454ec8a1 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2024-12-25 14:58:33 +00:00
Marwan Alwali
2dc1671902 update 2024-12-25 17:55:18 +03:00
c9d9e57115 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2024-12-25 14:53:32 +00:00
ab097f333c update 2024-12-25 14:52:36 +00:00
Marwan Alwali
b6486bb657 update 2024-12-25 17:51:07 +03:00
Marwan Alwali
ab657348e6 update 2024-12-24 18:35:30 +03:00
Marwan Alwali
8f59cc6723 update 2024-12-24 18:33:17 +03:00
940b9c0292 update 2024-12-24 15:32:02 +00:00
Marwan Alwali
5397363716 update 2024-12-24 17:38:26 +03:00
Marwan Alwali
ff85feccdf update 2024-12-24 17:13:00 +03:00
8a9ccf26c7 lMerge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2024-12-24 13:54:41 +00:00
9051840904 update 2024-12-24 13:49:36 +00:00
Marwan Alwali
167b6862e9 update 2024-12-24 16:48:01 +03:00
Marwan Alwali
9e8ef1978f update 2024-12-23 17:49:53 +03:00
Marwan Alwali
c6a802e377 update 2024-12-23 17:48:22 +03:00
Marwan Alwali
92e94e7265 update 2024-12-23 17:41:24 +03:00
15e2b227a6 ledger update 2024-12-23 14:39:57 +00:00
9209bab9ad ledger update 2024-12-23 14:38:14 +00:00
Marwan Alwali
d57702ea7a update 2024-12-23 11:55:41 +03:00
Marwan Alwali
1396294e4b update 2024-12-22 18:20:12 +03:00
Marwan Alwali
58295c3fba update 2024-12-22 18:19:05 +03:00
faf5f14881 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2024-12-22 15:18:14 +00:00
cb89dd450b update 2024-12-22 15:14:28 +00:00
Marwan Alwali
231c9b5638 update 2024-12-22 15:51:35 +03:00
Marwan Alwali
791e74b3d3 update 2024-12-19 20:08:14 +03:00
Marwan Alwali
152518ebdc update 2024-12-19 20:04:22 +03:00
4fea4e43eb more clean and fixes 2024-12-19 17:02:24 +00:00
f0f9dfc65e cleanup and refactoring 2024-12-18 16:08:34 +00:00
1238c5bac5 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2024-12-17 14:42:49 +00:00
645ba6ede0 fix the dealer update form 2024-12-17 14:40:11 +00:00
Marwan Alwali
2b74f92ab6 update 2024-12-17 17:29:08 +03:00
Marwan Alwali
28ac0c99d8 Merge branch 'main' of http://10.10.1.120:3000/tenhal_admin/haikal 2024-12-17 17:20:06 +03:00
Marwan Alwali
d9dc7f3323 Hajat Kateer 2024-12-17 17:16:51 +03:00
f98513f7d5 update 2024-12-17 14:08:40 +00:00
0d16ef4520 before merge 2024-12-17 13:33:59 +00:00
Marwan Alwali
d32ac2ab18 Hajat Kateer 2024-12-17 16:29:10 +03:00
Marwan Alwali
4e63d63c2c edit styles 2024-12-12 11:01:37 +03:00
Marwan Alwali
7597eb5391 edit styles 2024-12-12 11:00:55 +03:00
Marwan Alwali
b227d9ff5b edit styles 2024-12-12 11:00:42 +03:00
Marwan Alwali
9e0824de6d add car location 2024-12-11 22:04:21 +03:00
Marwan Alwali
9422426762 add qotation-02 2024-12-11 15:57:33 +03:00
Marwan Alwali
51fdc0b31f add qotation-02 2024-12-11 15:55:27 +03:00
05486e3d62 fix car cratea functionality 2024-12-11 12:52:58 +00:00
Marwan Alwali
88e81fadf1 add qotation
# Conflicts:
#	car_inventory/settings.py
#	inventory/models.py
#	inventory/services.py
#	inventory/urls.py
#	inventory/views.py
2024-12-10 14:01:53 +03:00
Marwan Alwali
6cf77729a6 first commit 2024-12-10 13:53:13 +03:00
6eb4fddded add vendor 2024-12-10 10:25:57 +00:00
2dfbb5fa9a add search to select fields, redirect logged in user to landingpage if they are authenticated 2024-12-10 10:15:22 +00:00
Marwan Alwali
9eba42aa91 first commit 2024-12-08 16:23:12 +03:00
Marwan Alwali
5371042919 first commit 2024-12-08 16:20:31 +03:00
Marwan Alwali
6b3367fa29 first commit 2024-12-08 14:54:49 +03:00
Marwan Alwali
4878963409 first commit 2024-12-08 14:48:20 +03:00
Marwan Alwali
a1a8713b2a first commit 2024-12-08 14:16:59 +03:00
Marwan Alwali
997b3cef10 first commit 2024-12-08 14:07:50 +03:00
7509 changed files with 20674972 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

22
.dockerignore Normal file
View File

@ -0,0 +1,22 @@
__pycache__/
*.pyc
*.log
*.sqlite3
*.db
migrations/
media/
static/
node_modules/
venv/
env/
.git/
.gitignore
.DS_Store
docker-compose.yml
README.md
car*.json
.vscode
.idea
*/migrations/*
*/migrations/
inventory/migrations/

146
.gitignore vendored Normal file
View File

@ -0,0 +1,146 @@
# Django #
*.log
*.pot
*.pyc
__pycache__
**/*__pycache__
db.sqlite
db.sqlite3
db.sqlite3.backup
db.sqlite*
media
car*.json
car_inventory/settings.py
scripts/dsrpipe.py
# Backup files #
*.bak
# If you are using PyCharm #
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
Makefile
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# File-based project format
*.iws
# IntelliJ
out/
# JIRA plugin
atlassian-ide-plugin.xml
# Python #
*.py[cod]
*$py.class
# Distribution / packaging
.Python build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.whl
*.egg-info/
.installed.cfg
*.egg
*.manifest
*.spec
inventory/management/commands/run.py
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
.pytest_cache/
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery
celerybeat-schedule.*
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# mkdocs documentation
/site
# mypy
.mypy_cache/
# Sublime Text #
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
*.sublime-workspace
*.sublime-project
# sftp configuration file
sftp-config.json
# Package control specific files Package
Control.last-run
Control.ca-list
Control.ca-bundle
Control.system-ca-bundle
GitHub.sublime-settings
# Visual Studio Code #
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history

BIN
.idea/.DS_Store generated vendored Normal file

Binary file not shown.

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

7
.idea/JetClient/state.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JetClientState">
<option name="id" value="9643c603-9e26-490a-916b-222ca66b0b6e" />
<option name="version" value="3" />
</component>
</project>

47
.idea/car_inventory.iml generated Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="FacetManager">
<facet type="django" name="Django">
<configuration>
<option name="rootFolder" value="$MODULE_DIR$" />
<option name="settingsModule" value="car_inventory/settings.py" />
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
<option name="environment" value="&lt;map/&gt;" />
<option name="doNotUseTestRunner" value="false" />
<option name="trackFilePattern" value="migrations" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="jquery-3.5.1" level="application" />
<orderEntry type="library" name="sweetalert2" level="application" />
<orderEntry type="library" name="jquery" level="application" />
<orderEntry type="library" name="bootstrap-icons" level="application" />
<orderEntry type="library" name="quagga" level="application" />
<orderEntry type="library" name="@zxing" level="application" />
<orderEntry type="library" name="tesseract.js" level="application" />
<orderEntry type="library" name="line" level="application" />
<orderEntry type="library" name="@turf/turf" level="application" />
<orderEntry type="library" name="apexcharts" level="application" />
<orderEntry type="library" name="moment.js" level="application" />
<orderEntry type="library" name="moment-timezone" level="application" />
<orderEntry type="library" name="fullcalendar" level="application" />
<orderEntry type="library" name="popper.js" level="application" />
<orderEntry type="library" name="tempusdominus-bootstrap-4" level="application" />
<orderEntry type="library" name="chart.js" level="application" />
<orderEntry type="library" name="htmx.org" level="application" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Django" />
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$MODULE_DIR$/templates" />
</list>
</option>
</component>
</module>

20
.idea/dataSources.xml generated Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="db" uuid="3573a7a1-f2cc-4e7d-8280-f91580f8eeac">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/db.sqlite3</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
</library>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
</library>
</libraries>
</data-source>
</component>
</project>

View File

@ -0,0 +1,500 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AngularAmbiguousComponentTag" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularBindingTypeMismatch" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularCliAddDependency" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="AngularDeferBlockOnTrigger" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularForBlockNonIterableVar" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularInaccessibleSymbol" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularIncorrectBlockUsage" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularIncorrectLetUsage" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularIncorrectTemplateDefinition" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularInsecureBindingToEvent" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="AngularInvalidAnimationTriggerAssignment" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularInvalidEntryComponent" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularInvalidI18nAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="AngularInvalidImportedOrDeclaredSymbol" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularInvalidSelector" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularInvalidTemplateReferenceVariable" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularMissingEventHandler" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularMissingOrInvalidDeclarationInModule" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularMissingRequiredDirectiveInputBinding" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularMultipleStructuralDirectives" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularNgOptimizedImage" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="AngularNonEmptyNgContent" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularNonStandaloneComponentImports" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularRecursiveModuleImportExport" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularUndefinedBinding" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularUndefinedModuleExport" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularUndefinedTag" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularUnresolvedPipe" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularUnsupportedSyntax" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AngularUnusedComponentImport" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="Annotator" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="AnonymousFunctionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AssignmentResultUsedJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AssignmentToForLoopParameterJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AssignmentToFunctionParameterJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="BeatScheduleCeleryTaskInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="BlockStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="BreakStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="BreakStatementWithLabelJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ChainedEqualityJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ChainedFunctionCallJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CheckEmptyScriptTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckImageSize" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckValidXmlInScriptTagBody" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CommandLineInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ComposeMissingKeys" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="ComposeUnknownKeys" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="ComposeUnknownValues" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="ComposeUnquotedPorts" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="ConditionalExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ConditionalExpressionWithIdenticalBranchesJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ConfusingFloatingPointLiteralJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ConfusingPlusesOrMinusesJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ConstanceFieldsetsMissingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstanceSettingUsageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstantOnLHSOfComparisonJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ConstantOnRHSOfComparisonJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ContinueStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ContinueStatementWithLabelJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssBrowserCompatibilityForProperties" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssConvertColorToHexInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssConvertColorToRgbInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssInvalidNestedSelector" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssMissingSemicolon" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CyclicJobDependency" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CyclomaticComplexityJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="10" />
</inspection_tool>
<inspection_tool class="CythonUsageBeforeDeclarationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DbtConfigurationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DebuggerStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="DefaultNotLastCaseInSwitchJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="DevContainerIdeSettings" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="DigiPythonLocal" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DivideByZeroJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="DjangoBrokenLineCommentInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoCloseTagInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoIncompatibleInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoOrmInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoRelationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoUnresolvedFilterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoUnresolvedLoadInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoUnresolvedStaticReferenceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoUnresolvedTagInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoUnresolvedTemplateReferenceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DjangoUrlArgumentsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DockerFileAddOrCopyPaths" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DockerFileArgumentCount" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="DockerFileAssignments" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="DockerFileRunCommandMissingContinuation" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="DockerJsonFormStringLiterals" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DocumentWriteJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="DuplicateConditionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="DuplicateKeyInSection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DuplicateSectionInFile" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DuplicatedBlockNamesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DuplicatedCode" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="DynamicallyGeneratedCodeJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ES6TopLevelAwaitExpression" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="EditorConfigCharClassLetterRedundancy" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigCharClassRedundancy" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigDeprecatedDescriptor" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigEmptyHeader" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigEmptySection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigEncoding" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigHeaderUniqueness" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigKeyCorrectness" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigListAcceptability" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigMissingRequiredDeclaration" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigNoMatchingFiles" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigNumerousWildcards" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigOptionRedundancy" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigPairAcceptability" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigPartialOverride" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigPatternEnumerationRedundancy" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigPatternRedundancy" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigReferenceCorrectness" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigRootDeclarationCorrectness" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigRootDeclarationUniqueness" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigShadowedOption" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigShadowingOption" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigSpaceInHeader" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigUnexpectedComma" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigUnusedDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EditorConfigValueCorrectness" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigValueUniqueness" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigVerifyByCore" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="EditorConfigWildcardRedundancy" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EmptyCatchBlockJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="EmptyFinallyBlockJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="EmptyTryBlockJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="EndBlockNamesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ExtendsTagPositionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ForLoopReplaceableByWhileJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_ignoreLoopsWithoutConditions" value="false" />
</inspection_tool>
<inspection_tool class="ForLoopThatDoesntUseLoopVariableJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="FunctionNamingConventionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_regex" value="[a-z][A-Za-z]*" />
<option name="m_minLength" value="4" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="FunctionWithInconsistentReturnsJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="FunctionWithMultipleLoopsJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="FunctionWithMultipleReturnPointsJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GithubFunctionSignatureValidation" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
<inspection_tool class="HtmlDeprecatedAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlDeprecatedTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlExtraClosingTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlFormInputWithoutLabel" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlMissingClosingTag" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="HtmlRequiredAltAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlRequiredLangAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlRequiredTitleElement" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownAnchorTarget" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownBooleanAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownTag" enabled="false" level="WARNING" enabled_by_default="false">
<option name="myValues">
<value>
<list size="6">
<item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" />
<item index="3" class="java.lang.String" itemvalue="noscript" />
<item index="4" class="java.lang.String" itemvalue="embed" />
<item index="5" class="java.lang.String" itemvalue="script" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="HtmlUnknownTarget" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlWrongAttributeValue" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HttpClientInappropriateProtocolUsageInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="HttpClientRunRequestNameInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="HttpClientUnresolvedAuthId" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="HttpClientUnresolvedVariable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestContentLengthIsIgnored" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestCustomHttpMethodInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestEnvironmentAuthConfigurationValidationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestJsonBodyInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestPlaceholder" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestRequestSeparatorJsonBodyInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestRequestSeparatorXmlBodyInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestRequestSeparatorYamlBodyInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="HttpRequestWhitespaceInsideRequestTargetPath" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="HttpUrlsUsage" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="IfStatementWithIdenticalBranchesJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="IfStatementWithTooManyBranchesJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="3" />
</inspection_tool>
<inspection_tool class="IgnoreFileDuplicateEntry" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="IllegalJobDependency" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="IncorrectHttpHeaderInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="IncrementDecrementResultUsedJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="InjectedReferences" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="InnerHTMLJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JSClassNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JSDeclarationsAtScopeStart" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="JSEqualityComparisonWithCoercion.TS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JSHint" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="JSNonStrictModeUsed" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JSUnfilteredForInLoop" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JSXSyntaxUsed" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="JetClientJson5StandardCompliance" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="JetClientJsonStandardCompliance" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="JsCoverageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="Json5StandardCompliance" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="JsonDuplicatePropertyKeys" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JsonPathEvaluateUnknownKey" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JsonPathUnknownFunction" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JsonPathUnknownOperator" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JsonSchemaCompliance" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JsonSchemaDeprecation" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="JsonSchemaRefReference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JsonStandardCompliance" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="LabeledStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="LessResolvedByNameOnly" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="LessUnresolvedMixin" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="LessUnresolvedVariable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="LocalVariableNamingConventionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_regex" value="[a-z][A-Za-z]*" />
<option name="m_minLength" value="1" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="LossyEncoding" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MagicNumberJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MaliciousLibrariesLocal" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MandatoryParamsAbsent" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="MarkdownIncorrectTableFormatting" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="MarkdownIncorrectlyNumberedListItem" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MarkdownLinkDestinationWithSpaces" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MarkdownNoTableBorders" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MarkdownOutdatedTableOfContents" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MarkdownUnresolvedFileReference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MarkdownUnresolvedHeaderReference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MarkdownUnresolvedLinkLabel" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MicroPythonLocal" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MongoJSDeprecationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MongoJSExtDeprecationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MongoJSExtResolveInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MongoJSExtSideEffectsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MongoJSResolveInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MongoJSSideEffectsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MsBuiltinInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MsOrderByInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="MysqlLoadDataPathInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MysqlParsingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MysqlSpaceAfterFunctionNameInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="NegatedConditionalExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NegatedIfStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NestedAssignmentJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NestedConditionalExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NestedFunctionCallJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NestedFunctionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_includeAnonymousFunctions" value="false" />
</inspection_tool>
<inspection_tool class="NestedSwitchStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NestingDepthJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="5" />
</inspection_tool>
<inspection_tool class="NonAsciiCharacters" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NonBlockStatementBodyJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ObjectAllocationIgnoredJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="OraMissingBodyInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OraOverloadInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OraUnmatchedForwardDeclarationInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="OverlyComplexArithmeticExpressionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="6" />
</inspection_tool>
<inspection_tool class="OverlyComplexBooleanExpressionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="3" />
</inspection_tool>
<inspection_tool class="ParameterNamingConventionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_regex" value="[a-z][A-Za-z]*" />
<option name="m_minLength" value="1" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="ParametersPerFunctionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="5" />
</inspection_tool>
<inspection_tool class="PgSelectFromProcedureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PlatformDetectionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PoetryPackageVersionsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PointlessBitwiseExpressionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_ignoreExpressionsContainingConstants" value="false" />
</inspection_tool>
<inspection_tool class="PostCssNesting" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Puppet3Deprecations" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="Puppet4Deprecations" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PuppetMultipleHashSetParamsPerResourceInstance" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="PuppetUnresolved" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyAbstractClassInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyArgumentListInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyAssignmentToLoopOrWithParameterInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyAsyncCallInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyAttributeOutsideInitInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyBroadExceptionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyByteLiteralInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyCallingNonCallableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyChainedComparisonsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyClassHasNoInitInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyClassVarInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyComparisonWithNoneInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyCoverageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyDataclassInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyDecoratorInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyDefaultArgumentInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyDeprecationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyDictCreationInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyDictDuplicateKeysInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyDocstringTypesInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyDunderSlotsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyExceptClausesOrderInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyExceptionInheritInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyFinalInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyFromFutureImportInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyGlobalUndefinedInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyInconsistentIndentationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyIncorrectDocstringInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyInitNewSignatureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyListCreationInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyMethodFirstArgAssignmentInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyMethodMayBeStaticInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyMethodOverridingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyMethodParametersInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyMissingConstructorInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyNamedTupleInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyNestedDecoratorsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyNewStyleGenericSyntaxInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyNonAsciiCharInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyNoneFunctionAssignmentInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyOldStyleClassesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyOverloadsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyOverridesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="WARNING" enabled_by_default="false">
<option name="ignoredPackages">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="Django" />
<item index="1" class="java.lang.String" itemvalue="django-admin-volt" />
<item index="2" class="java.lang.String" itemvalue="faker_food" />
<item index="3" class="java.lang.String" itemvalue="typing_extensions" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyPandasSeriesToListInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyPep8Inspection" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="PyPep8NamingInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyPropertyAccessInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyPropertyDefinitionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyProtectedMemberInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyProtocolInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyRedeclarationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyRedundantParenthesesInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyRelativeImportInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyReturnFromInitInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PySetFunctionToLiteralInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyShadowingBuiltinsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyShadowingNamesInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PySimplifyBooleanCheckInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PySingleQuotedDocstringInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyStatementEffectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyStringFormatInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyStubPackagesAdvertiser" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyStubPackagesCompatibilityInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PySuperArgumentsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyTestParametrizedInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyTestUnpassedFixtureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyTrailingSemicolonInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyTupleAssignmentBalanceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyTupleItemAssignmentInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyTypeCheckerInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyTypeHintsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyTypedDictInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyUnboundLocalVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyUnnecessaryBackslashInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyUnreachableCodeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyUnusedLocalInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PyVulnerableApiCodeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PydanticInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyramidSetupInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ReassignedToPlainText" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RedundantSuppression" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpDuplicateAlternationBranch" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpDuplicateCharacterInClass" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpEmptyAlternationBranch" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpEscapedMetaCharacter" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="RegExpOctalEscape" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="RegExpRedundantClassElement" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpRedundantEscape" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpRedundantNestedCharacterClass" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpRepeatedSpace" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpSimplifiable" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpSingleCharAlternation" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpSuspiciousBackref" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpUnexpectedAnchor" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RegExpUnnecessaryNonCapturingGroup" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ReplaceAssignmentWithOperatorAssignmentJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="RequiredAttributes" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ReuseOfLocalVariableJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ShellCheck" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false" />
<inspection_tool class="SqlAddNotNullColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAggregatesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAmbiguousColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCallNotationInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SqlCaseVsCoalesceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCaseVsIfInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCheckUsingColumnsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlConstantExpressionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCurrentSchemaInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDeprecateTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDerivedTableAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDropIndexedColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDtInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDuplicateColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlIdentifierInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlIllegalCursorStateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertIntoGeneratedColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertNullIntoNotNullInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertValuesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlJoinWithoutOnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlMisleadingReferenceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlMissingReturnInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SqlMultipleLimitClausesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantCodeInCoalesceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantElseNullInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantLimitInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantOrderingDirectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlResolveInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SqlShadowingAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlShouldBeInGroupByInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSideEffectsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSignatureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlStorageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlStringLengthExceededInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTransactionStatementInTriggerInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTriggerTransitionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnicodeStringLiteralInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnreachableCodeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedCteInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedSubqueryItemInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlWithoutWhereInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="StandardJS" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="StatementsPerFunctionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="30" />
</inspection_tool>
<inspection_tool class="StringLiteralBreaksHTMLJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Stylelint" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="SwJsonMaybeSpecificationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SwJsonUnresolvedReferencesInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SwYamlMaybeSpecificationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SwYamlUnresolvedReferencesInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="TailRecursionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="TaskProblemsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TextLabelInSwitchStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ThreeNegationsPerFunctionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="TomlUnresolvedReference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TrailingSpacesInProperty" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TsLint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UndefinedAction" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UndefinedParamsPresent" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnresolvedReference" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="UnsatisfiedRequirementInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnterminatedStatementJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoreSemicolonAtEndOfBlock" value="true" />
</inspection_tool>
<inspection_tool class="UnusedCatchParameterJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_ignoreCatchBlocksWithComments" value="false" />
</inspection_tool>
<inspection_tool class="UnusedProperty" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="VoidExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="VueDataFunction" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="VueDeprecatedSymbol" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="VueDuplicateTag" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="VueMissingComponentImportInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="VueUnrecognizedDirective" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="VueUnrecognizedSlot" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="VulnerableLibrariesLocal" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="WrongPropertyKeyValueDelimiter" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="XHTMLIncompatabilitiesJS" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

6
.idea/jsLibraryMappings.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$" libraries="{@turf/turf, @zxing, apexcharts, bootstrap-icons, chart.js, fullcalendar, htmx.org, jquery, jquery-3.5.1, line, moment-timezone, moment.js, popper.js, quagga, sweetalert2, tempusdominus-bootstrap-4, tesseract.js}" />
</component>
</project>

12
.idea/material_theme_project_new.xml generated Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="-4d33890d:18fe9fd09b1:-7ffe" />
</MTProjectMetadataState>
</option>
</component>
</project>

10
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.11 (car_inventory)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (car_inventory)" project-jdk-type="Python SDK" />
<component name="PyPackaging">
<option name="earlyReleasesAsUpgrades" value="true" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/car_inventory.iml" filepath="$PROJECT_DIR$/.idea/car_inventory.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

20
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Django",
"type": "debugpy",
"request": "launch",
"args": [
"runserver",
"0.0.0.0:8888"
],
"django": true,
"autoStartBrowser": false,
"program": "${workspaceFolder}/manage.py"
}
]
}

39
Dockerfile Normal file
View File

@ -0,0 +1,39 @@
# Use an official Python image as a base
FROM python:3.11.11-slim-bullseye
# Set the working directory to /app
WORKDIR /app
# Create a new user and group
RUN groupadd -r appgroup
RUN useradd -r -g appgroup -G appgroup -m -d /app -s /bin/false appuser
# Copy the requirements file
COPY requirements.txt .
# Install the dependencies
RUN pip install -r requirements.txt
RUN apt-get update && apt-get install -y libgl1
RUN apt-get update && apt-get install -y libglib2.0-dev
RUN apt-get update && apt-get install -y libzbar0
# Copy the application code
COPY . .
# Expose the port
EXPOSE 8000
# Copy the entrypoint script
COPY entrypoint.sh /app/entrypoint.sh
# Make the script executable
RUN chmod +x /app/entrypoint.sh
# Change ownership of the app directory to the new user
RUN chown -R appuser:appgroup /app
RUN find /app -path "*/migrations/*.py" -not -name "__init__.py" -delete
RUN find /app -path "*/migrations/*.pyc" -delete
# Set the entrypoint to execute the script as the new user
ENTRYPOINT ["sh", "-c", "python3 manage.py makemigrations && python3 manage.py migrate && python3 manage.py collectstatic --no-input && python3 manage.py runserver 0.0.0.0:8000"]

0
api/__init__.py Normal file
View File

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.

Binary file not shown.

5
api/admin.py Normal file
View File

@ -0,0 +1,5 @@
from django.contrib import admin
from . import models
admin.site.register(models.CarVIN)

6
api/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api'

35
api/consumers.py Normal file
View File

@ -0,0 +1,35 @@
# from channels.generic.websocket import AsyncWebsocketConsumer
# from api.services import get_car_data
# import json
#
#
# class VINScanConsumer(AsyncWebsocketConsumer):
# def __init__(self, *args, **kwargs):
# super().__init__(args, kwargs)
# self.group_name = None
#
# async def connect(self):
# self.group_name = 'vin_scan_group'
# await self.channel_layer.group_add(
# self.group_name,
# self.channel_name
# )
# await self.accept()
#
# async def disconnect(self, close_code):
# await self.channel_layer.group_discard(
# self.group_name,
# self.channel_name
# )
#
# async def receive(self, text_data, **kwargs):
# data = json.loads(text_data)
# vin = data['vin']
# get_car_data(vin)
# # Process the VIN as needed, e.g., save to the database
#
# # Send data back to the WebSocket
# await self.send(text_data=json.dumps({
# 'message': 'VIN received',
# 'vin': vin
# }))

View File

@ -0,0 +1,22 @@
# Generated by Django 5.1.5 on 2025-01-30 11:28
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='CarVIN',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('vin', models.CharField(max_length=17, verbose_name='VIN')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='created')),
],
),
]

View File

Binary file not shown.

11
api/models.py Normal file
View File

@ -0,0 +1,11 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class CarVIN(models.Model):
vin = models.CharField(max_length=17, verbose_name=_("VIN"))
created = models.DateTimeField(auto_now_add=True, verbose_name="created")
def __str__(self):
return self.vin

7
api/routing.py Normal file
View File

@ -0,0 +1,7 @@
# from django.urls import re_path
# from api import consumers
#
# websocket_urlpatterns = [
# re_path(r'ws/vin_scan/$', consumers.VINScanConsumer.as_asgi()),
# ]

83
api/serializers.py Normal file
View File

@ -0,0 +1,83 @@
from . import models
from rest_framework import serializers
from inventory import models as inventory_models
class CarVINSerializer(serializers.ModelSerializer):
class Meta:
model = models.CarVIN
fields = ['vin']
def create(self, validated_data):
vin = validated_data.pop('vin')
return models.CarVIN.objects.create(vin=vin, **validated_data)
class CarMakeSerializer(serializers.ModelSerializer):
car_models = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='carmodel_set')
class Meta:
model = inventory_models.CarMake
fields = '__all__'
class CarModelSerializer(serializers.ModelSerializer):
car_series = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='carserie_set')
class Meta:
model = inventory_models.CarModel
fields = '__all__'
class CarSerieSerializer(serializers.ModelSerializer):
car_trims = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='cartrim_set')
class Meta:
model = inventory_models.CarSerie
fields = '__all__'
class CarTrimSerializer(serializers.ModelSerializer):
car_equipments = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='carequipment_set')
car_specification_values = serializers.PrimaryKeyRelatedField(many=True, read_only=True,
source='carspecificationvalue_set')
class Meta:
model = inventory_models.CarTrim
fields = '__all__'
class CarEquipmentSerializer(serializers.ModelSerializer):
car_option_values = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='caroptionvalue_set')
class Meta:
model = inventory_models.CarEquipment
fields = '__all__'
class CarSpecificationSerializer(serializers.ModelSerializer):
child_specifications = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='carspecification_set')
class Meta:
model = inventory_models.CarSpecification
fields = '__all__'
class CarSpecificationValueSerializer(serializers.ModelSerializer):
class Meta:
model = inventory_models.CarSpecificationValue
fields = '__all__'
class CarOptionSerializer(serializers.ModelSerializer):
child_options = serializers.PrimaryKeyRelatedField(many=True, read_only=True, source='caroption_set')
class Meta:
model = inventory_models.CarOption
fields = '__all__'
class CarOptionValueSerializer(serializers.ModelSerializer):
class Meta:
model = inventory_models.CarOptionValue
fields = '__all__'

63
api/services.py Normal file
View File

@ -0,0 +1,63 @@
import hashlib
import json
import requests
def get_bearer():
api_token = "f5204a00-6f31-4de2-96d8-ed998e0d230c"
api_secret = "8c11320781a5b8f4f327b6937e6f8241"
url = "https://carapi.app/api/auth/login"
headers = {
"accept": "text/plain",
"Content-Type": "application/json"
}
data = {
"api_token": api_token,
"api_secret": api_secret
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
return response.text
else:
print("the api key or secret is not valid")
return None
def get_car_data(vin):
url = f"https://carapi.app/api/vin/{vin}?verbose=no&all_trims=no"
headers = {
"Authorization": f"Bearer {get_bearer()}"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status() # Raises an HTTPError for bad responses (4XX, 5XX)
response = response.json()
print(response)
except requests.exceptions.HTTPError as http_err:
print(f"HTTP error occurred: {http_err}")
except requests.exceptions.RequestException as err:
print(f"Error occurred: {err}")
except Exception as e:
print(f"An error occurred: {e}")
def get_from_cardatabase(vin):
vin = vin
url = "https://api.vehicledatabases.com/premium/vin-decode/{vin}"
payload = {}
headers = {
'x-AuthKey': '3cefdfd4272445f1929b5801c55d8fa5'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)

797
api/temp.txt Normal file
View File

@ -0,0 +1,797 @@
# url = f"https://carapi.app/api/vin/{vin}?verbose=no&all_trims=no"
# headers = {
# "Authorization": f"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjYXJhcGkuYXBwIiwic3ViIjoiYjU1OGYzMDMtODI0Ni00NjgzLTkwYTQtZmYwMGQxYWNmNGU3IiwiYXVkIjoiYjU1OGYzMDMtODI0Ni00NjgzLTkwYTQtZmYwMGQxYWNmNGU3IiwiZXhwIjoxNzI0MzgyODMzLCJpYXQiOjE3MjM3NzgwMzMsImp0aSI6IjA3ZDUzM2Y5LWRmNzEtNDM1My1hMTBhLTNiYmQ2MDljNWM0YiIsInVzZXIiOnsic3Vic2NyaWJlZCI6dHJ1ZSwic3Vic2NyaXB0aW9uIjoic3RhcnRlciIsInJhdGVfbGltaXRfdHlwZSI6ImhhcmQiLCJhZGRvbnMiOnsiYW50aXF1ZV92ZWhpY2xlcyI6ZmFsc2UsImRhdGFfZmVlZCI6ZmFsc2V9fX0.KnaH-dOGcmJAF3WqzrZ_c_eFtkSjPVEjR15G7KFxi2s"
# }
#
# try:
# response = requests.get(url, headers=headers)
# response.raise_for_status() # Raises an HTTPError for bad responses (4XX, 5XX)
#
# response = response.json()
# print(response)
#
# except requests.exceptions.HTTPError as http_err:
# print(f"HTTP error occurred: {http_err}")
# except requests.exceptions.RequestException as err:
# print(f"Error occurred: {err}")
# except Exception as e:
# print(f"An error occurred: {e}")
# class TokenAuthenticationMiddleware(MiddlewareMixin):
#
# def process_request(self, request, *args, **kwargs):
#
# exempt_paths = ['/login/', '/signup/', '/']
# if request.path in exempt_paths:
# return None
#
# token_key = request.META.get('HTTP_AUTHORIZATION')
# if token_key:
# token_key = token_key.split(' ')[1] if ' ' in token_key else token_key
# try:
# token = Token.objects.get(key=token_key)
# request.user = token.user
# except Token.DoesNotExist:
# return HttpResponseForbidden("Invalid token")
#
# if not request.user.is_authenticated:
# return HttpResponseForbidden("You are not authorized to view this page")
#
# return None
# def vin_decode(vin):
# apiKey = "67b751455994"
# secretKey = "2ca9c09960"
# apiPrefix = "https://api.vindecoder.eu/3.2"
# id = "decode"
#
# controlSum = hashlib.sha1((vin.upper() + "|" + id + "|" + apiKey + "|" + secretKey).encode('utf-8')).hexdigest()[
# :10]
# url = apiPrefix + "/" + apiKey + "/" + controlSum + "/decode/" + vin.upper() + ".json"
# print(url)
# json_data = requests.get(url).json()
# print(json_data)
# return json_data
{
"year": 2007,
"make": "CHEVROLET",
"model": "TrailBlazer",
"trim": "1/2 Ton",
"specs": {
"active_safety_system_note": null,
"adaptive_cruise_control_acc": null,
"adaptive_driving_beam_adb": null,
"anti_lock_braking_system_abs": null,
"auto_reverse_system_for_windows_and_sunroofs": null,
"automatic_crash_notification_acn_advanced_automatic_crash_notification_aacn": null,
"automatic_pedestrian_alerting_sound_for_hybrid_and_ev_only": null,
"axle_configuration": null,
"axles": null,
"backup_camera": null,
"base_price": null,
"battery_current_amps_from": null,
"battery_current_amps_to": null,
"battery_energy_kwh_from": null,
"battery_energy_kwh_to": null,
"battery_type": null,
"battery_voltage_volts_from": null,
"battery_voltage_volts_to": null,
"bed_length_inches": null,
"bed_type": null,
"blind_spot_intervention_bsi": null,
"blind_spot_warning_bsw": null,
"body_class": "Sport Utility Vehicle (SUV)/Multi-Purpose Vehicle (MPV)",
"brake_system_description": null,
"brake_system_type": "Hydraulic",
"bus_floor_configuration_type": "Not Applicable",
"bus_length_feet": null,
"bus_type": "Not Applicable",
"cab_type": null,
"charger_level": null,
"charger_power_kw": null,
"cooling_type": "Water",
"crash_imminent_braking_cib": null,
"curb_weight_pounds": null,
"curtain_air_bag_locations": null,
"custom_motorcycle_type": "Not Applicable",
"daytime_running_light_drl": null,
"destination_market": null,
"displacement_cc": "4200.0",
"displacement_ci": "256.29972519787",
"displacement_l": "4.2",
"doors": "4",
"drive_type": "4x2",
"dynamic_brake_support_dbs": null,
"electrification_level": null,
"electronic_stability_control_esc": null,
"engine_brake_hp_from": null,
"engine_brake_hp_to": null,
"engine_configuration": "In-Line",
"engine_manufacturer": "GM",
"engine_model": "LL8",
"engine_number_of_cylinders": "6",
"engine_power_kw": null,
"engine_stroke_cycles": null,
"entertainment_system": null,
"ev_drive_unit": null,
"event_data_recorder_edr": null,
"forward_collision_warning_fcw": null,
"front_air_bag_locations": null,
"fuel_delivery_fuel_injection_type": "Multipoint Fuel Injection (MPFI)",
"fuel_type_primary": "Gasoline",
"fuel_type_secondary": null,
"gross_combination_weight_rating_from": null,
"gross_combination_weight_rating_to": null,
"gross_vehicle_weight_rating_from": "Class 1D: 5,001 - 6,000 lb (2,268 - 2,722 kg)",
"gross_vehicle_weight_rating_to": null,
"headlamp_light_source": null,
"keyless_ignition": null,
"knee_air_bag_locations": null,
"lane_centering_assistance": null,
"lane_departure_warning_ldw": null,
"lane_keeping_assistance_lka": null,
"manufacturer_name": "GENERAL MOTORS LLC",
"motorcycle_chassis_type": "Not Applicable",
"motorcycle_suspension_type": "Not Applicable",
"ncsa_body_type": "Compact Utility (Utility Vehicle Categories \"Small\" and \"Midsize\")",
"ncsa_make": "Chevrolet",
"ncsa_model": "TrailBlazer (2003 on; for 2002 model, see 401)",
"ncsa_note": null,
"non_land_use": null,
"note": null,
"number_of_battery_cells_per_module": null,
"number_of_battery_modules_per_pack": null,
"number_of_battery_packs_per_vehicle": null,
"number_of_seat_rows": null,
"number_of_seats": null,
"number_of_wheels": null,
"other_battery_info": null,
"other_bus_info": null,
"other_engine_info": "MFI, DOHC, Aluminium",
"other_motorcycle_info": null,
"other_restraint_system_info": null,
"other_trailer_info": null,
"parking_assist": null,
"pedestrian_automatic_emergency_braking_paeb": null,
"plant_city": "MORAINE",
"plant_company_name": "GM Truck Group",
"plant_country": "UNITED STATES (USA)",
"plant_state": "OHIO",
"possible_values": "",
"pretensioner": null,
"rear_automatic_emergency_braking": null,
"rear_cross_traffic_alert": null,
"sae_automation_level_from": null,
"sae_automation_level_to": null,
"seat_belt_type": null,
"seat_cushion_air_bag_locations": null,
"semiautomatic_headlamp_beam_switching": null,
"series": "1/2 Ton",
"series2": null,
"side_air_bag_locations": null,
"steering_location": null,
"suggested_vin": "",
"tire_pressure_monitoring_system_tpms_type": null,
"top_speed_mph": null,
"track_width_inches": null,
"traction_control": null,
"trailer_body_type": "Not Applicable",
"trailer_length_feet": null,
"trailer_type_connection": "Not Applicable",
"transmission_speeds": null,
"transmission_style": null,
"trim": null,
"trim2": null,
"turbo": null,
"valve_train_design": "Dual Overhead Cam (DOHC)",
"vehicle_descriptor": "1GNDS13S*72",
"vehicle_type": "MULTIPURPOSE PASSENGER VEHICLE (MPV)",
"wheel_base_inches_from": null,
"wheel_base_inches_to": null,
"wheel_base_type": null,
"wheel_size_front_inches": null,
"wheel_size_rear_inches": null,
"windows": null
},
"trims": [
{
"id": 40805,
"make_model_id": 33,
"year": 2007,
"name": "LS",
"description": "LS 4dr SUV (4.2L 6cyl 4A)",
"msrp": 25045,
"invoice": 23417,
"created": "2023-06-29T21:13:16-04:00",
"modified": "2023-06-29T21:13:16-04:00",
"make_model_trim_mileage": {
"id": 40805,
"make_model_trim_id": 40805,
"fuel_tank_capacity": "22.0",
"combined_mpg": 16,
"epa_city_mpg": 14,
"epa_highway_mpg": 20,
"range_city": 308,
"range_highway": 440,
"battery_capacity_electric": null,
"epa_time_to_charge_hr_240v_electric": null,
"epa_kwh_100_mi_electric": null,
"range_electric": null,
"epa_highway_mpg_electric": null,
"epa_city_mpg_electric": null,
"epa_combined_mpg_electric": null
},
"make_model_trim_engine": {
"id": 40805,
"make_model_trim_id": 40805,
"engine_type": "gas",
"fuel_type": "regular unleaded",
"cylinders": "I6",
"size": "4.2",
"horsepower_hp": 291,
"horsepower_rpm": 6000,
"torque_ft_lbs": 277,
"torque_rpm": 4800,
"valves": 24,
"valve_timing": "Variable",
"cam_type": "Double overhead cam (DOHC)",
"drive_type": "rear wheel drive",
"transmission": "4-speed automatic"
},
"make_model_trim_body": {
"id": 40805,
"make_model_trim_id": 40805,
"type": "SUV",
"doors": 5,
"length": "191.8",
"width": "74.7",
"seats": 5,
"height": "72.5",
"wheel_base": "113.0",
"front_track": "62.7",
"rear_track": "62.0",
"ground_clearance": "7.8",
"cargo_capacity": "43.7",
"max_cargo_capacity": "80.1",
"curb_weight": 4356,
"gross_weight": 5550,
"max_payload": 1194,
"max_towing_capacity": 6800
},
"make_model": {
"id": 33,
"make_id": 6,
"name": "TrailBlazer",
"make": {
"id": 6,
"name": "Chevrolet"
}
}
},
{
"id": 40806,
"make_model_id": 33,
"year": 2007,
"name": "LS",
"description": "LS 4dr SUV 4WD (4.2L 6cyl 4A)",
"msrp": 27340,
"invoice": 25563,
"created": "2023-06-29T21:13:16-04:00",
"modified": "2023-06-29T21:13:16-04:00",
"make_model_trim_mileage": {
"id": 40806,
"make_model_trim_id": 40806,
"fuel_tank_capacity": "22.0",
"combined_mpg": 16,
"epa_city_mpg": 14,
"epa_highway_mpg": 20,
"range_city": 308,
"range_highway": 440,
"battery_capacity_electric": null,
"epa_time_to_charge_hr_240v_electric": null,
"epa_kwh_100_mi_electric": null,
"range_electric": null,
"epa_highway_mpg_electric": null,
"epa_city_mpg_electric": null,
"epa_combined_mpg_electric": null
},
"make_model_trim_engine": {
"id": 40806,
"make_model_trim_id": 40806,
"engine_type": "gas",
"fuel_type": "regular unleaded",
"cylinders": "I6",
"size": "4.2",
"horsepower_hp": 291,
"horsepower_rpm": 6000,
"torque_ft_lbs": 277,
"torque_rpm": 4800,
"valves": 24,
"valve_timing": "Variable",
"cam_type": "Double overhead cam (DOHC)",
"drive_type": "four wheel drive",
"transmission": "4-speed automatic"
},
"make_model_trim_body": {
"id": 40806,
"make_model_trim_id": 40806,
"type": "SUV",
"doors": 5,
"length": "191.8",
"width": "74.7",
"seats": 5,
"height": "72.5",
"wheel_base": "113.0",
"front_track": "62.7",
"rear_track": "62.0",
"ground_clearance": "7.8",
"cargo_capacity": "43.7",
"max_cargo_capacity": "80.1",
"curb_weight": 4523,
"gross_weight": 5750,
"max_payload": 1227,
"max_towing_capacity": 6600
},
"make_model": {
"id": 33,
"make_id": 6,
"name": "TrailBlazer",
"make": {
"id": 6,
"name": "Chevrolet"
}
}
},
{
"id": 40807,
"make_model_id": 33,
"year": 2007,
"name": "LT",
"description": "LT 4dr SUV (4.2L 6cyl 4A)",
"msrp": 27970,
"invoice": 26152,
"created": "2023-06-29T21:13:16-04:00",
"modified": "2023-06-29T21:13:16-04:00",
"make_model_trim_mileage": {
"id": 40807,
"make_model_trim_id": 40807,
"fuel_tank_capacity": "22.0",
"combined_mpg": 16,
"epa_city_mpg": 14,
"epa_highway_mpg": 20,
"range_city": 308,
"range_highway": 440,
"battery_capacity_electric": null,
"epa_time_to_charge_hr_240v_electric": null,
"epa_kwh_100_mi_electric": null,
"range_electric": null,
"epa_highway_mpg_electric": null,
"epa_city_mpg_electric": null,
"epa_combined_mpg_electric": null
},
"make_model_trim_engine": {
"id": 40807,
"make_model_trim_id": 40807,
"engine_type": "gas",
"fuel_type": "regular unleaded",
"cylinders": "I6",
"size": "4.2",
"horsepower_hp": 291,
"horsepower_rpm": 6000,
"torque_ft_lbs": 277,
"torque_rpm": 4800,
"valves": 24,
"valve_timing": "Variable",
"cam_type": "Double overhead cam (DOHC)",
"drive_type": "rear wheel drive",
"transmission": "4-speed automatic"
},
"make_model_trim_body": {
"id": 40807,
"make_model_trim_id": 40807,
"type": "SUV",
"doors": 5,
"length": "191.8",
"width": "74.7",
"seats": 5,
"height": null,
"wheel_base": "113.0",
"front_track": "62.7",
"rear_track": "62.0",
"ground_clearance": "7.8",
"cargo_capacity": "43.7",
"max_cargo_capacity": "80.1",
"curb_weight": 4356,
"gross_weight": 5550,
"max_payload": 1194,
"max_towing_capacity": 6800
},
"make_model": {
"id": 33,
"make_id": 6,
"name": "TrailBlazer",
"make": {
"id": 6,
"name": "Chevrolet"
}
}
},
{
"id": 40808,
"make_model_id": 33,
"year": 2007,
"name": "LT",
"description": "LT 4dr SUV 4WD (4.2L 6cyl 4A)",
"msrp": 30210,
"invoice": 28246,
"created": "2023-06-29T21:13:16-04:00",
"modified": "2023-06-29T21:13:16-04:00",
"make_model_trim_mileage": {
"id": 40808,
"make_model_trim_id": 40808,
"fuel_tank_capacity": "22.0",
"combined_mpg": 16,
"epa_city_mpg": 14,
"epa_highway_mpg": 20,
"range_city": 308,
"range_highway": 440,
"battery_capacity_electric": null,
"epa_time_to_charge_hr_240v_electric": null,
"epa_kwh_100_mi_electric": null,
"range_electric": null,
"epa_highway_mpg_electric": null,
"epa_city_mpg_electric": null,
"epa_combined_mpg_electric": null
},
"make_model_trim_engine": {
"id": 40808,
"make_model_trim_id": 40808,
"engine_type": "gas",
"fuel_type": "regular unleaded",
"cylinders": "I6",
"size": "4.2",
"horsepower_hp": 291,
"horsepower_rpm": 6000,
"torque_ft_lbs": 277,
"torque_rpm": 4800,
"valves": 24,
"valve_timing": "Variable",
"cam_type": "Double overhead cam (DOHC)",
"drive_type": "four wheel drive",
"transmission": "4-speed automatic"
},
"make_model_trim_body": {
"id": 40808,
"make_model_trim_id": 40808,
"type": "SUV",
"doors": 5,
"length": "191.8",
"width": "74.7",
"seats": 5,
"height": null,
"wheel_base": "113.0",
"front_track": "62.7",
"rear_track": "62.0",
"ground_clearance": "7.8",
"cargo_capacity": "43.7",
"max_cargo_capacity": "80.1",
"curb_weight": 4523,
"gross_weight": 5750,
"max_payload": 1227,
"max_towing_capacity": 6600
},
"make_model": {
"id": 33,
"make_id": 6,
"name": "TrailBlazer",
"make": {
"id": 6,
"name": "Chevrolet"
}
}
},
{
"id": 40809,
"make_model_id": 33,
"year": 2007,
"name": "SS",
"description": "SS 4dr SUV (6.0L 8cyl 4A)",
"msrp": 31320,
"invoice": 29284,
"created": "2023-06-29T21:13:16-04:00",
"modified": "2023-06-29T21:13:16-04:00",
"make_model_trim_mileage": {
"id": 40809,
"make_model_trim_id": 40809,
"fuel_tank_capacity": "22.0",
"combined_mpg": 15,
"epa_city_mpg": 13,
"epa_highway_mpg": 17,
"range_city": 286,
"range_highway": 374,
"battery_capacity_electric": null,
"epa_time_to_charge_hr_240v_electric": null,
"epa_kwh_100_mi_electric": null,
"range_electric": null,
"epa_highway_mpg_electric": null,
"epa_city_mpg_electric": null,
"epa_combined_mpg_electric": null
},
"make_model_trim_engine": {
"id": 40809,
"make_model_trim_id": 40809,
"engine_type": "gas",
"fuel_type": "premium unleaded (required)",
"cylinders": "V8",
"size": "6.0",
"horsepower_hp": 395,
"horsepower_rpm": 5400,
"torque_ft_lbs": 400,
"torque_rpm": 4400,
"valves": 16,
"valve_timing": null,
"cam_type": "Overhead valves (OHV)",
"drive_type": "rear wheel drive",
"transmission": "4-speed automatic"
},
"make_model_trim_body": {
"id": 40809,
"make_model_trim_id": 40809,
"type": "SUV",
"doors": 5,
"length": "191.8",
"width": "74.7",
"seats": 5,
"height": "67.8",
"wheel_base": "113.0",
"front_track": "62.7",
"rear_track": "62.0",
"ground_clearance": "7.8",
"cargo_capacity": "43.7",
"max_cargo_capacity": "80.1",
"curb_weight": 4496,
"gross_weight": 6001,
"max_payload": 1505,
"max_towing_capacity": 6800
},
"make_model": {
"id": 33,
"make_id": 6,
"name": "TrailBlazer",
"make": {
"id": 6,
"name": "Chevrolet"
}
}
},
{
"id": 40810,
"make_model_id": 33,
"year": 2007,
"name": "SS",
"description": "SS 4dr SUV AWD (6.0L 8cyl 4A)",
"msrp": 33620,
"invoice": 31435,
"created": "2023-06-29T21:13:16-04:00",
"modified": "2023-06-29T21:13:16-04:00",
"make_model_trim_mileage": {
"id": 40810,
"make_model_trim_id": 40810,
"fuel_tank_capacity": "22.0",
"combined_mpg": 14,
"epa_city_mpg": 12,
"epa_highway_mpg": 16,
"range_city": 264,
"range_highway": 352,
"battery_capacity_electric": null,
"epa_time_to_charge_hr_240v_electric": null,
"epa_kwh_100_mi_electric": null,
"range_electric": null,
"epa_highway_mpg_electric": null,
"epa_city_mpg_electric": null,
"epa_combined_mpg_electric": null
},
"make_model_trim_engine": {
"id": 40810,
"make_model_trim_id": 40810,
"engine_type": "gas",
"fuel_type": "premium unleaded (required)",
"cylinders": "V8",
"size": "6.0",
"horsepower_hp": 395,
"horsepower_rpm": 5400,
"torque_ft_lbs": 400,
"torque_rpm": 4400,
"valves": 16,
"valve_timing": null,
"cam_type": "Overhead valves (OHV)",
"drive_type": "all wheel drive",
"transmission": "4-speed automatic"
},
"make_model_trim_body": {
"id": 40810,
"make_model_trim_id": 40810,
"type": "SUV",
"doors": 5,
"length": "191.8",
"width": "74.7",
"seats": 5,
"height": "67.8",
"wheel_base": "113.0",
"front_track": "62.7",
"rear_track": "62.0",
"ground_clearance": "7.8",
"cargo_capacity": "43.7",
"max_cargo_capacity": "80.1",
"curb_weight": 4663,
"gross_weight": 6001,
"max_payload": 1338,
"max_towing_capacity": 6600
},
"make_model": {
"id": 33,
"make_id": 6,
"name": "TrailBlazer",
"make": {
"id": 6,
"name": "Chevrolet"
}
}
},
{
"id": 40812,
"make_model_id": 33,
"year": 2007,
"name": "SS",
"description": "SS 4dr SUV AWD w/3SS (6.0L 8cyl 4A)",
"msrp": 37125,
"invoice": 34712,
"created": "2023-06-29T21:13:16-04:00",
"modified": "2023-06-29T21:13:16-04:00",
"make_model_trim_mileage": {
"id": 40812,
"make_model_trim_id": 40812,
"fuel_tank_capacity": "22.0",
"combined_mpg": 14,
"epa_city_mpg": 12,
"epa_highway_mpg": 16,
"range_city": 264,
"range_highway": 352,
"battery_capacity_electric": null,
"epa_time_to_charge_hr_240v_electric": null,
"epa_kwh_100_mi_electric": null,
"range_electric": null,
"epa_highway_mpg_electric": null,
"epa_city_mpg_electric": null,
"epa_combined_mpg_electric": null
},
"make_model_trim_engine": {
"id": 40812,
"make_model_trim_id": 40812,
"engine_type": "gas",
"fuel_type": "premium unleaded (required)",
"cylinders": "V8",
"size": "6.0",
"horsepower_hp": 395,
"horsepower_rpm": 5400,
"torque_ft_lbs": 400,
"torque_rpm": 4400,
"valves": 16,
"valve_timing": null,
"cam_type": "Overhead valves (OHV)",
"drive_type": "all wheel drive",
"transmission": "4-speed automatic"
},
"make_model_trim_body": {
"id": 40812,
"make_model_trim_id": 40812,
"type": "SUV",
"doors": 5,
"length": "191.8",
"width": "74.7",
"seats": 5,
"height": "67.8",
"wheel_base": "113.0",
"front_track": "62.7",
"rear_track": "62.0",
"ground_clearance": "7.8",
"cargo_capacity": "43.7",
"max_cargo_capacity": "80.1",
"curb_weight": 4663,
"gross_weight": 6001,
"max_payload": 1338,
"max_towing_capacity": 6600
},
"make_model": {
"id": 33,
"make_id": 6,
"name": "TrailBlazer",
"make": {
"id": 6,
"name": "Chevrolet"
}
}
},
{
"id": 40811,
"make_model_id": 33,
"year": 2007,
"name": "SS",
"description": "SS 4dr SUV w/3SS (6.0L 8cyl 4A)",
"msrp": 34885,
"invoice": 32617,
"created": "2023-06-29T21:13:16-04:00",
"modified": "2023-06-29T21:13:16-04:00",
"make_model_trim_mileage": {
"id": 40811,
"make_model_trim_id": 40811,
"fuel_tank_capacity": "22.0",
"combined_mpg": 15,
"epa_city_mpg": 13,
"epa_highway_mpg": 17,
"range_city": 286,
"range_highway": 374,
"battery_capacity_electric": null,
"epa_time_to_charge_hr_240v_electric": null,
"epa_kwh_100_mi_electric": null,
"range_electric": null,
"epa_highway_mpg_electric": null,
"epa_city_mpg_electric": null,
"epa_combined_mpg_electric": null
},
"make_model_trim_engine": {
"id": 40811,
"make_model_trim_id": 40811,
"engine_type": "gas",
"fuel_type": "premium unleaded (required)",
"cylinders": "V8",
"size": "6.0",
"horsepower_hp": 395,
"horsepower_rpm": 5400,
"torque_ft_lbs": 400,
"torque_rpm": 4400,
"valves": 16,
"valve_timing": null,
"cam_type": "Overhead valves (OHV)",
"drive_type": "rear wheel drive",
"transmission": "4-speed automatic"
},
"make_model_trim_body": {
"id": 40811,
"make_model_trim_id": 40811,
"type": "SUV",
"doors": 5,
"length": "191.8",
"width": "74.7",
"seats": 5,
"height": "67.8",
"wheel_base": "113.0",
"front_track": "62.7",
"rear_track": "62.0",
"ground_clearance": "7.8",
"cargo_capacity": "43.7",
"max_cargo_capacity": "80.1",
"curb_weight": 4496,
"gross_weight": 6001,
"max_payload": 1505,
"max_towing_capacity": 6800
},
"make_model": {
"id": 33,
"make_id": 6,
"name": "TrailBlazer",
"make": {
"id": 6,
"name": "Chevrolet"
}
}
}
]
}

3
api/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

23
api/urls.py Normal file
View File

@ -0,0 +1,23 @@
from django.urls import path, include
from rest_framework import routers
from api import views
router = routers.DefaultRouter()
router.register(r'car-makes', views.CarMakeViewSet)
router.register(r'car-models', views.CarModelViewSet)
router.register(r'car-series', views.CarSerieViewSet)
router.register(r'car-trims', views.CarTrimViewSet)
router.register(r'car-equipments', views.CarEquipmentViewSet)
router.register(r'car-specifications', views.CarSpecificationViewSet)
router.register(r'car-specification-values', views.CarSpecificationValueViewSet)
router.register(r'car-options', views.CarOptionViewSet)
router.register(r'car-option-values', views.CarOptionValueViewSet)
urlpatterns = [
path('', include(router.urls)),
path('cars/vin/', views.CarVINViewSet.as_view(), name='car_vin'),
path("cars/", views.car_list, name="car-list"),
path('login/', views.LoginView.as_view(), name='login'),
]

127
api/views.py Normal file
View File

@ -0,0 +1,127 @@
from django.core.paginator import Paginator
from django.db.models import Q
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework import permissions, status, viewsets, generics
from rest_framework.views import APIView
from rest_framework.response import Response
from django.contrib.auth import authenticate
from django.shortcuts import render
from inventory.utils import get_user_type
from . import models, serializers
from .services import get_car_data, get_from_cardatabase
from rest_framework.authtoken.models import Token
from django.utils.decorators import method_decorator
from inventory import models as inventory_models
class LoginView(APIView):
permission_classes = [permissions.AllowAny,]
def post(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
if username is None or password is None:
return Response({'error': 'Please provide both username and password.'}, status=status.HTTP_400_BAD_REQUEST)
user = authenticate(username=username, password=password)
if not user:
return Response({'error': 'Invalid credentials.'}, status=status.HTTP_401_UNAUTHORIZED)
token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key, 'user_id': user.id, 'username': user.username}, status=status.HTTP_200_OK)
class CarVINViewSet(APIView):
queryset = models.CarVIN.objects.all().order_by('-created')
serializer_class = serializers.CarVINSerializer
def get(self, request):
vin = models.CarVIN.objects.all()
serializer = serializers.CarVINSerializer(vin, many=True)
return Response(serializer.data)
def post(self, request):
serializer = serializers.CarVINSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
for key, value in serializer.validated_data.items():
print(key, value)
get_car_data(value)
# get_from_cardatabase(value)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CarMakeViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarMake.objects.filter(is_sa_import=True)
serializer_class = serializers.CarMakeSerializer
class CarModelViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarModel.objects.filter(id_car_make__is_sa_import=True)
serializer_class = serializers.CarModelSerializer
class CarSerieViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarSerie.objects.all()
serializer_class = serializers.CarSerieSerializer
class CarTrimViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarTrim.objects.all()
serializer_class = serializers.CarTrimSerializer
class CarEquipmentViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarEquipment.objects.all()
serializer_class = serializers.CarEquipmentSerializer
class CarSpecificationViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarSpecification.objects.all()
serializer_class = serializers.CarSpecificationSerializer
class CarSpecificationValueViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarSpecificationValue.objects.all()
serializer_class = serializers.CarSpecificationValueSerializer
class CarOptionViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarOption.objects.all()
serializer_class = serializers.CarOptionSerializer
class CarOptionValueViewSet(viewsets.ModelViewSet):
queryset = inventory_models.CarOptionValue.objects.all()
serializer_class = serializers.CarOptionValueSerializer
def car_list(request):
dealer = get_user_type(request)
page = request.GET.get("page", 1)
per_page = 10
cars = inventory_models.Car.objects.filter(dealer=dealer).values(
"vin",
"id_car_make__name",
"id_car_model__name",
"status"
)
paginator = Paginator(cars, per_page)
page_obj = paginator.get_page(page)
return JsonResponse({
"data": list(page_obj), # Convert QuerySet to list
"page": page_obj.number, # Current page number
"per_page": per_page,
"total_pages": paginator.num_pages, # Total pages
"total_items": paginator.count # Total records
})

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

27
car_inventory/asgi.py Normal file
View File

@ -0,0 +1,27 @@
"""
ASGI config for car_inventory project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
"""
# asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from api import routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'car_inventory.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
routing.websocket_urlpatterns
)
),
})

34
car_inventory/urls.py Normal file
View File

@ -0,0 +1,34 @@
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
from django.conf.urls.i18n import i18n_patterns
from inventory import views
import debug_toolbar
from schema_graph.views import Schema
# from two_factor.urls import urlpatterns as tf_urls
urlpatterns = [
path('__debug__/', include(debug_toolbar.urls)),
path('silk/', include('silk.urls', namespace='silk')),
path('api-auth/', include('rest_framework.urls')),
path('api/', include('api.urls')),
path('dj-rest-auth/', include('dj_rest_auth.urls')),
]
urlpatterns += i18n_patterns(
path('admin/', admin.site.urls),
path('switch_language/', views.switch_language, name='switch_language'),
path('accounts/', include('allauth.urls')),
path('prometheus/', include('django_prometheus.urls')),
path('', include('inventory.urls')),
path('ledger/', include('django_ledger.urls', namespace='django_ledger')),
path("haikalbot/", include("haikalbot.urls")),
path('appointment/', include('appointment.urls')),
path('plans/', include('plans.urls')),
path("schema/", Schema.as_view()),
# path('', include(tf_urls)),
)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

16
car_inventory/wsgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
WSGI config for car_inventory project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'car_inventory.settings')
application = get_wsgi_application()

249082
carequipment_backup.json Normal file

File diff suppressed because it is too large Load Diff

4523
carmake_backup.json Normal file

File diff suppressed because it is too large Load Diff

47720
carmodel_backup.json Normal file

File diff suppressed because it is too large Load Diff

338249
caroption_backup.json Normal file

File diff suppressed because it is too large Load Diff

17738173
caroptionvalue_backup.json Normal file

File diff suppressed because it is too large Load Diff

191066
carserie_backup.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,830 @@
[
{
"model": "inventory.carspecification",
"pk": 1,
"fields": {
"name": "Bodywork",
"arabic_name": "هيكل السيارة",
"id_parent": null
}
},
{
"model": "inventory.carspecification",
"pk": 2,
"fields": {
"name": "Body type",
"arabic_name": "نوع الهيكل",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 3,
"fields": {
"name": "Number of doors",
"arabic_name": "عدد الأبواب",
"id_parent": 1549
}
},
{
"model": "inventory.carspecification",
"pk": 4,
"fields": {
"name": "Number of seater",
"arabic_name": "عدد المقاعد",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 5,
"fields": {
"name": "Length",
"arabic_name": "الطول",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 6,
"fields": {
"name": "Width",
"arabic_name": "العرض",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 7,
"fields": {
"name": "Height",
"arabic_name": "الارتفاع",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 8,
"fields": {
"name": "Wheelbase",
"arabic_name": "قاعدة العجلات",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 9,
"fields": {
"name": "Front track",
"arabic_name": "المسار الأمامي",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 10,
"fields": {
"name": "Rear track",
"arabic_name": "المسافة الخلفية بين العجلات",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 11,
"fields": {
"name": "Engine",
"arabic_name": "محرك",
"id_parent": null
}
},
{
"model": "inventory.carspecification",
"pk": 12,
"fields": {
"name": "Engine type",
"arabic_name": "نوع المحرك",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 13,
"fields": {
"name": "Capacity",
"arabic_name": "السعة",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 14,
"fields": {
"name": "Engine power",
"arabic_name": "قوة المحرك",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 15,
"fields": {
"name": "Max power at RPM",
"arabic_name": "الحد الأقصى للقوة عند عدد الدورات في الدقيقة",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 16,
"fields": {
"name": "Maximum torque",
"arabic_name": "أقصى عزم دوران",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 17,
"fields": {
"name": "Injection type",
"arabic_name": "نوع الحقن",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 19,
"fields": {
"name": "Cylinder layout",
"arabic_name": "تخطيط الأسطوانات",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 20,
"fields": {
"name": "Number of cylinders",
"arabic_name": "عدد الأسطوانات",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 21,
"fields": {
"name": "Compression ratio",
"arabic_name": "نسبة الانضغاط",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 22,
"fields": {
"name": "Fuel",
"arabic_name": "وقود",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 23,
"fields": {
"name": "Gearbox and handling",
"arabic_name": "علبة التروس والتحكم",
"id_parent": null
}
},
{
"model": "inventory.carspecification",
"pk": 24,
"fields": {
"name": "Gearbox type",
"arabic_name": "نوع علبة التروس",
"id_parent": 23
}
},
{
"model": "inventory.carspecification",
"pk": 26,
"fields": {
"name": "Number of gear",
"arabic_name": "عدد التروس",
"id_parent": 23
}
},
{
"model": "inventory.carspecification",
"pk": 27,
"fields": {
"name": "Drive wheels",
"arabic_name": "عجلات القيادة",
"id_parent": 23
}
},
{
"model": "inventory.carspecification",
"pk": 29,
"fields": {
"name": "Front brakes",
"arabic_name": "الفرامل الأمامية",
"id_parent": 40
}
},
{
"model": "inventory.carspecification",
"pk": 30,
"fields": {
"name": "Rear brakes",
"arabic_name": "الفرامل الخلفية",
"id_parent": 40
}
},
{
"model": "inventory.carspecification",
"pk": 31,
"fields": {
"name": "Operating characteristics",
"arabic_name": "خصائص التشغيل",
"id_parent": null
}
},
{
"model": "inventory.carspecification",
"pk": 32,
"fields": {
"name": "Max speed",
"arabic_name": "السرعة القصوى",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 33,
"fields": {
"name": "Acceleration (0-100 km/h)",
"arabic_name": "التسارع (0-100 كم/ساعة)",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 34,
"fields": {
"name": "Curb weight",
"arabic_name": "وزن السيارة الفارغة",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 35,
"fields": {
"name": "Fuel tank capacity",
"arabic_name": "سعة خزان الوقود",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 36,
"fields": {
"name": "Wheel size",
"arabic_name": "حجم العجلة",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 37,
"fields": {
"name": "Emission standards",
"arabic_name": "معايير الانبعاثات",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 38,
"fields": {
"name": "Ground clearance",
"arabic_name": "الخلوص الأرضي",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 39,
"fields": {
"name": "Valves per cylinder",
"arabic_name": "صمامات لكل أسطوانة",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 40,
"fields": {
"name": "Suspension and brakes",
"arabic_name": "نظام التعليق والفرامل",
"id_parent": null
}
},
{
"model": "inventory.carspecification",
"pk": 41,
"fields": {
"name": "Front suspension",
"arabic_name": "التعليق الأمامي",
"id_parent": 40
}
},
{
"model": "inventory.carspecification",
"pk": 42,
"fields": {
"name": "Back suspension",
"arabic_name": "التعليق الخلفي",
"id_parent": 40
}
},
{
"model": "inventory.carspecification",
"pk": 44,
"fields": {
"name": "Max trunk capacity",
"arabic_name": "أقصى سعة لصندوق الأمتعة",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 45,
"fields": {
"name": "Min trunk capacity",
"arabic_name": "سعة صندوق الأمتعة الدنيا",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 46,
"fields": {
"name": "Boost type",
"arabic_name": "نوع التعزيز",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 47,
"fields": {
"name": "Cylinder bore",
"arabic_name": "تجويف الأسطوانة",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 48,
"fields": {
"name": "Stroke cycle",
"arabic_name": "دورة الأشواط",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 50,
"fields": {
"name": "City driving fuel consumption per 100 km",
"arabic_name": "استهلاك الوقود في القيادة داخل المدينة لكل 100 كيلومتر",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 51,
"fields": {
"name": "Highway driving fuel consumption per 100 km",
"arabic_name": "استهلاك الوقود على الطرق السريعة لكل 100 كم",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 52,
"fields": {
"name": "Mixed driving fuel consumption per 100 km",
"arabic_name": "استهلاك الوقود في القيادة المختلطة لكل 100 كيلومتر",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 55,
"fields": {
"name": "Engine model",
"arabic_name": "نموذج المحرك",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 57,
"fields": {
"name": "Turning circle",
"arabic_name": "دائرة الدوران",
"id_parent": 23
}
},
{
"model": "inventory.carspecification",
"pk": 58,
"fields": {
"name": "Full weight",
"arabic_name": "الوزن الكامل",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 59,
"fields": {
"name": "Disc size",
"arabic_name": "حجم القرص",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 61,
"fields": {
"name": "Engine placement",
"arabic_name": "موضع المحرك",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 62,
"fields": {
"name": "Cruising range",
"arabic_name": "مدى القيادة",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 66,
"fields": {
"name": "Car width with mirrors",
"arabic_name": "عرض السيارة مع المرايا",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1549,
"fields": {
"name": "General information",
"arabic_name": "معلومات عامة",
"id_parent": null
}
},
{
"model": "inventory.carspecification",
"pk": 1551,
"fields": {
"name": "Safety",
"arabic_name": "السلامة",
"id_parent": null
}
},
{
"model": "inventory.carspecification",
"pk": 1552,
"fields": {
"name": "Country",
"arabic_name": "بلد",
"id_parent": 1549
}
},
{
"model": "inventory.carspecification",
"pk": 1553,
"fields": {
"name": "Car class",
"arabic_name": "فئة السيارة",
"id_parent": 1549
}
},
{
"model": "inventory.carspecification",
"pk": 1554,
"fields": {
"name": "Clearance",
"arabic_name": "الخلوص",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1555,
"fields": {
"name": "Front track width",
"arabic_name": "عرض المسار الأمامي",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1556,
"fields": {
"name": "Back track width",
"arabic_name": "عرض المسار الخلفي",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1559,
"fields": {
"name": "Max power (kW)",
"arabic_name": "القدرة القصوى (كيلوواط)",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 1561,
"fields": {
"name": "CO2 emissions",
"arabic_name": "انبعاثات ثاني أكسيد الكربون",
"id_parent": 31
}
},
{
"model": "inventory.carspecification",
"pk": 1562,
"fields": {
"name": "Safety assessment",
"arabic_name": "تقييم السلامة",
"id_parent": 1551
}
},
{
"model": "inventory.carspecification",
"pk": 1563,
"fields": {
"name": "Rating name",
"arabic_name": "اسم التقييم",
"id_parent": 1551
}
},
{
"model": "inventory.carspecification",
"pk": 1564,
"fields": {
"name": "Turnover of maximum torque",
"arabic_name": "دوران أقصى عزم",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 1565,
"fields": {
"name": "Payload",
"arabic_name": "الحمولة",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1566,
"fields": {
"name": "Presence of intercooler",
"arabic_name": "وجود مبرد داخلي",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 1567,
"fields": {
"name": "Trailer load (with brakes)",
"arabic_name": "حمولة المقطورة (مع الفرامل)",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1568,
"fields": {
"name": "Front/rear axle load",
"arabic_name": "حمولة المحور الأمامي/الخلفي",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1569,
"fields": {
"name": "Loading height",
"arabic_name": "ارتفاع التحميل",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1570,
"fields": {
"name": "Cargo compartment (Length x Width x Height)",
"arabic_name": "مقصورة الشحن (الطول × العرض × الارتفاع)",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1571,
"fields": {
"name": "Cargo compartment volume",
"arabic_name": "حجم حيز الأمتعة",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1631,
"fields": {
"name": "Accumulator battery",
"arabic_name": "بطارية تراكمية",
"id_parent": null
}
},
{
"model": "inventory.carspecification",
"pk": 1632,
"fields": {
"name": "Battery capacity",
"arabic_name": "سعة البطارية",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1634,
"fields": {
"name": "Electric power reserve",
"arabic_name": "احتياطي الطاقة الكهربائية",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1635,
"fields": {
"name": "Charging time",
"arabic_name": "وقت الشحن",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1641,
"fields": {
"name": "Steering wheel position",
"arabic_name": "موضع عجلة القيادة",
"id_parent": 1549
}
},
{
"model": "inventory.carspecification",
"pk": 1642,
"fields": {
"name": "Dimensions",
"arabic_name": "الأبعاد",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1644,
"fields": {
"name": "Pitch Circle Diameter",
"arabic_name": "قطر دائرة التثبيت",
"id_parent": 1
}
},
{
"model": "inventory.carspecification",
"pk": 1645,
"fields": {
"name": "Engine code",
"arabic_name": "رمز المحرك",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 1647,
"fields": {
"name": "Battery type",
"arabic_name": "نوع البطارية",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1648,
"fields": {
"name": "Timing belt",
"arabic_name": "حزام التوقيت",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 1649,
"fields": {
"name": "Flow calculation method",
"arabic_name": "طريقة حساب التدفق",
"id_parent": 11
}
},
{
"model": "inventory.carspecification",
"pk": 1650,
"fields": {
"name": "Battery temperature",
"arabic_name": "درجة حرارة البطارية",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1651,
"fields": {
"name": "Fast charge time",
"arabic_name": "وقت الشحن السريع",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1652,
"fields": {
"name": "Description of fast charging",
"arabic_name": "وصف الشحن السريع",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1653,
"fields": {
"name": "Charging connector type",
"arabic_name": "نوع موصل الشحن",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1654,
"fields": {
"name": "Consumption",
"arabic_name": "استهلاك",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1655,
"fields": {
"name": "Maximum charging power",
"arabic_name": "أقصى قدرة شحن",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1656,
"fields": {
"name": "Battery capacity (available)",
"arabic_name": "سعة البطارية (المتاحة)",
"id_parent": 1631
}
},
{
"model": "inventory.carspecification",
"pk": 1657,
"fields": {
"name": "Number of charging cycles",
"arabic_name": "عدد دورات الشحن",
"id_parent": 1631
}
}
]

Binary file not shown.

955880
cartrim_backup.json Normal file

File diff suppressed because it is too large Load Diff

31
docker-compose.yml Normal file
View File

@ -0,0 +1,31 @@
version: '3'
services:
db:
image: postgres
restart: always
environment:
- POSTGRES_DB=haikal_db
- POSTGRES_USER=haikal_user
- POSTGRES_PASSWORD=haikal_pass
healthcheck:
test: ["CMD", "pg_isready", "-U", "haikal_user", "-d", "haikal_db"]
interval: 1m30s
timeout: 30s
retries: 5
start_period: 30s
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
environment:
- DATABASE_HOST=db
- DATABASE_PORT=5432
- POSTGRES_DB=haikal_db
- POSTGRES_USER=haikal_user
- POSTGRES_PASSWORD=haikal_pass
volumes:
- .:/app
ports:
- "8000:8000"
depends_on:
- db

20
docs/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

35
docs/make.bat Normal file
View File

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

28
docs/source/conf.py Normal file
View File

@ -0,0 +1,28 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'Haikal'
copyright = '2024, Marwan Alwali'
author = 'Marwan Alwali'
release = '01/11/2024'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = []
templates_path = ['_templates']
exclude_patterns = []
language = '[en,ar]'
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = 'alabaster'
html_static_path = ['_static']

17
docs/source/index.rst Normal file
View File

@ -0,0 +1,17 @@
.. Haikal documentation master file, created by
sphinx-quickstart on Mon Nov 25 16:28:43 2024.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Haikal documentation
====================
Add your content using ``reStructuredText`` syntax. See the
`reStructuredText <https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`_
documentation for details.
.. toctree::
:maxdepth: 2
:caption: Contents:

5
entrypoint.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/sh
python manage.py migrate
python manage.py collectstatic --no-input
python manage.py runserver 0.0.0.0:8000

137
generate.py Normal file
View File

@ -0,0 +1,137 @@
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "car_inventory.settings")
django.setup()
from inventory.models import *
from rich import print
import random
import datetime
from inventory.services import decodevin
def run():
# car = Car.objects.filter(vin='2C3HD46R4WH170267')
vin_list = [
"1B3ES56C13D120225",
"1GB4KYC86FF131536",
"1HSHXAHR15J136217",
"1G1ZT52845F231124",
"1J4GK48K43W721617",
"JTDBE32K430163717",
"1J4FA69S05P331572",
"2FMGK5D86EBD28496",
"KNADE243696530337",
"1N4AL21EX8N499928",
"1N4AL21E49N400571",
"1G2NW12E54C145398",
"LGJE1EE09SM333542",
"LGJE1EE0XSM333551",
"LGJE1EE02SM333561",
"LGJE1EE0XSM333565",
"LGJE1EE01SM333549",
"LGJE1EE06SM333563",
"LGJE1EE04SM333562",
"LGJE1EE08SM333564",
"LFB1E6078P1Y01338",
"LGJE5EE02PM046815",
"LFB1E6074P1Y01742",
"LGJE5EE07PM132850",
"LGJE1EE08SM311094",
"LFPH4ACP4P2A00123",
"LFB1E6075R1Y00117",
"ZAMPP56F0J1282425",
"LGJE1EE06RM292314",
"LGJE1EE00NM013594",
"LFB1E6075M1Y00272",
"LFB1E6670P1Y00224",
"LFB1E6079N1Y00275",
"LGJE3FE00MM804819",
"LGJE3FE0XMM804844",
"LGJE1EE01RM200767",
"LGJE1EE08RM200703",
"ZAMXS57F7L1341373",
"LGJE5EE06SM330781",
"LFB1E6077P1Y02643",
"LFB1E6074M1Y00151",
"LGJE1EE07RM292323",
"LGJE1EE01RM200171",
"LGJE1EE04SM311545",
"LGJE1EE04RM292859",
"LGJE1EE02RM292861",
"LFB1E607XP1Y01454",
"LFB1E6073P1Y00081",
"LGJE1EE03PM129391",
"LGJE1EE03RM200639",
"LGJE1EE02PM128393",
"LGJE1EE03NM964436",
"LGJE1EE06RM211599",
"LGJE1EE06NM014104",
"LGJE1EE05NM014272",
"LGJE5EE06SM331641",
"LGJE1EE09NM013528",
"LGJE5EE0XPM048196",
"LGJE1EE01RM212935",
"LGJE1EE05RM200433",
"LGJE1EE05SM311909",
"LGJE5EE02SM346914",
"LGJE1EE08SM306753",
"LGJE1EE02SM312001",
"LFPH4ACP6R2A02586",
"LGJE1EE00PM048445",
"LGJE1EE02SM311902",
"LGJE1EE03SM312573",
"LGJE1EE00SM306813",
"LFB1E6674N1Y00577",
"LGJE1EE00SM306875",
"LGJE1EE04SM306863",
"LFB1E6079P1Y00389",
"LGJE1EE04SM311562",
"LGJE1EE01SM312006",
"LGJE1EE08SM312486",
"LFB1E6676P1Y00941",
"LFPH4ACP1M1B00116",
"LGJE1EE02SM312564",
"LFPH4BCPXS2L00051",
"LGJE1EE06SM306864",
]
for vin in vin_list:
try:
for _ in range(15):
dealer = Dealer.objects.get(user__email="marwan@tenhal.sa")
vin = f"{vin[:-4]}{random.randint(0, 9)}{random.randint(0, 9)}{random.randint(0, 9)}{random.randint(0, 9)}"
result = decodevin(vin)
make = CarMake.objects.get(name=result["maker"])
model = make.carmodel_set.filter(name__contains=result["model"]).first()
if not model or model == "":
model = random.choice(make.carmodel_set.all())
year = result["modelYear"]
serie = random.choice(model.carserie_set.all())
trim = random.choice(serie.cartrim_set.all())
car = Car.objects.create(
vin=vin,
id_car_make=make,
id_car_model=model,
id_car_serie=serie,
id_car_trim=trim,
year=(int(year) or 2025),
receiving_date=datetime.datetime.now(),
dealer=dealer,
)
car_finance = CarFinance.objects.create(
car=car, cost_price=10000, selling_price=20000
)
car_color = CarColors.objects.create(
car=car,
interior=random.choice(InteriorColors.objects.all()),
exterior=random.choice(ExteriorColors.objects.all()),
)
print(make, model, serie, trim)
except Exception as e:
print(e)
if __name__ == "__main__":
run()

0
haikalbot/__init__.py Normal file
View File

3
haikalbot/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
haikalbot/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class HaikalbotConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'haikalbot'

View File

@ -0,0 +1,45 @@
from openai import OpenAI
from inventory import models
from car_inventory import settings
def fetch_data(dealer):
try:
# Annotate total cars by make, model, and trim
cars = models.Car.objects.filter(dealer=dealer).count()
print(cars)
if cars:
return f"إجمالي عدد السيارات في المخزون الخاص بـ {dealer.get_local_name}) هو {cars}"
# return f"The total cars in {dealer} inventory is ( {cars} )."
else:
return "No cars found in the inventory."
except Exception as e:
return f"An error occurred while fetching car data: {str(e)}"
def get_gpt4_response(user_input, dealer):
dealer = dealer
client = OpenAI(api_key=settings.OPENAI_API_KEY)
# if "سيارة في المخزون" in user_input.lower():
# # cars = user_input.split("how many cars")[-1].strip()
# car_data = fetch_data(dealer)
# user_input += f" Relevant car data: {car_data}"
try:
completion = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": (
"You are an assistant specialized in car inventory management for the Haikal system. "
"You can answer questions about the inventory, sales process, car transfers, invoices, "
"and other application-specific functionalities. Always provide responses aligned "
"with the Haikal system's structure and features."
)
},
{"role": "user", "content": user_input},
],
)
return completion.choices[0].message.content.strip()
except Exception as e:
return f"An error occurred while generating the response: {str(e)}"

View File

@ -0,0 +1,23 @@
# Generated by Django 5.1.6 on 2025-03-06 01:43
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='ChatLog',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('user_message', models.TextField()),
('chatbot_response', models.TextField()),
('timestamp', models.DateTimeField(auto_now_add=True)),
],
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 5.1.6 on 2025-03-06 01:43
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('haikalbot', '0001_initial'),
('inventory', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='chatlog',
name='dealer',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chatlogs', to='inventory.dealer'),
),
]

View File

12
haikalbot/models.py Normal file
View File

@ -0,0 +1,12 @@
from django.db import models
from inventory.models import Dealer
class ChatLog(models.Model):
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='chatlogs')
user_message = models.TextField()
chatbot_response = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user_message

3
haikalbot/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

7
haikalbot/urls.py Normal file
View File

@ -0,0 +1,7 @@
from django.urls import path
from . import views
urlpatterns = [
path("", views.ChatbotView.as_view(), name="chatbot"),
]

26
haikalbot/views.py Normal file
View File

@ -0,0 +1,26 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View
from django.shortcuts import render
from django.http import JsonResponse
from .chatbot_logic import get_gpt4_response
import json
class ChatbotView(LoginRequiredMixin, View):
def get(self, request):
return render(request, "haikalbot/chatbot.html")
def post(self, request):
dealer = request.user.dealer
try:
data = json.loads(request.body)
user_message = data.get("message", "").strip()
if not user_message:
return JsonResponse({"error": "Message cannot be empty."}, status=400)
chatbot_response = get_gpt4_response(user_message, dealer)
return JsonResponse({"response": chatbot_response}, status=200)
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON format."}, status=400)

BIN
inventory/.DS_Store vendored Normal file

Binary file not shown.

0
inventory/__init__.py Normal file
View File

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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

160
inventory/admin.py Normal file
View File

@ -0,0 +1,160 @@
from appointment.models import Appointment
from django.contrib import admin
from . import models
from django_ledger import models as ledger_models
from django_pdf_actions.actions import export_to_pdf_landscape, export_to_pdf_portrait
from appointment import models as appointment_models
from import_export.admin import ExportMixin
from import_export.resources import ModelResource
from .models import Car
# # Define resource class
# class CarSerieResource(ModelResource):
# class Meta:
# model = models.CarSerie
#
# # Integrate into Django Admin
# @admin.register(models.CarSerie)
# class CarSeriesAdmin(ExportMixin, admin.ModelAdmin):
# resource_class = CarSerieResource
class CarTrimResource(ModelResource):
class Meta:
model = models.CarTrim
@admin.register(models.CarTrim)
class CarTrimAdmin(ExportMixin, admin.ModelAdmin):
resource_class = CarTrimResource
admin.site.register(models.Dealer)
admin.site.register(models.Staff)
admin.site.register(models.Vendor)
admin.site.register(models.DealerSettings)
# admin.site.register(models.SaleQuotation)
# admin.site.register(models.SaleQuotationCar)
admin.site.register(models.SaleOrder)
admin.site.register(models.CustomGroup)
admin.site.register(models.CarFinance)
admin.site.register(models.CarColors)
admin.site.register(models.CarRegistration)
admin.site.register(models.CustomCard)
admin.site.register(models.CarSpecificationValue)
admin.site.register(models.CarEquipment)
admin.site.register(models.CarOptionValue)
admin.site.register(models.ExteriorColors)
admin.site.register(models.InteriorColors)
# admin.site.register(models.Subscription)
# admin.site.register(models.SubscriptionPlan)
# admin.site.register(models.SubscriptionUser)
admin.site.register(models.CarLocation)
admin.site.register(models.CarReservation)
admin.site.register(models.Organization)
admin.site.register(models.Representative)
# admin.site.register(models.CarTrim)
admin.site.register(models.AdditionalServices)
admin.site.register(models.Payment)
admin.site.register(models.VatRate)
admin.site.register(ledger_models.CustomerModel)
admin.site.register(ledger_models.VendorModel)
admin.site.register(ledger_models.ItemModel)
admin.site.register(models.Opportunity)
admin.site.register(models.Notification)
admin.site.register(models.Lead)
admin.site.register(models.Activity)
admin.site.register(models.Schedule)
admin.site.register(models.Notes)
admin.site.register(models.UserActivityLog)
# admin.site.register(appointment_models.Client)
@admin.register(models.Car)
class CarAdmin(admin.ModelAdmin):
search_fields = ('vin',)
actions = [export_to_pdf_landscape, export_to_pdf_portrait]
@admin.register(models.CarMake)
class CarMakeAdmin(admin.ModelAdmin):
list_display = ('name', 'arabic_name', 'is_sa_import')
search_fields = ('name', 'arabic_name')
list_filter = ('is_sa_import', 'name',)
actions = [export_to_pdf_landscape, export_to_pdf_portrait]
class Meta:
verbose_name = "Car Make"
ordering = ('name',)
@admin.register(models.CarModel)
class CarModelAdmin(admin.ModelAdmin):
list_display = ('name', 'arabic_name', 'id_car_make', 'get_is_sa_import')
search_fields = ('id_car_model', 'name', 'arabic_name')
list_filter = ('id_car_make__is_sa_import', 'id_car_make')
sortable_by = ['name', 'arabic_name', 'id_car_make']
def get_is_sa_import(self, obj):
return obj.id_car_make.is_sa_import
get_is_sa_import.boolean = True
get_is_sa_import.short_description = 'Is SA Import'
class Meta:
verbose_name = "Car Model"
ordering = ('name',)
@admin.register(models.CarSerie)
class CarSeriesAdmin(admin.ModelAdmin):
list_display = ('name', 'arabic_name', 'id_car_model', )
search_fields = ('name',)
list_filter = ('id_car_model__id_car_make__is_sa_import',
'id_car_model__id_car_make__name',)
class Meta:
verbose_name = "Car Series"
# @admin.register(models.CarTrim)
# class CarTrimAdmin(admin.ModelAdmin):
# list_display = ('name', 'arabic_name',
# 'id_car_serie__name',
# 'id_car_serie__id_car_model__name',
# 'id_car_serie__id_car_model__id_car_make__name')
# search_fields = ('name', 'arabic_name', 'id_car_serie__id_car_model__name')
# list_filter = ('id_car_serie__id_car_model__id_car_make__is_sa_import',
# 'id_car_serie__id_car_model__id_car_make__name')
#
# class Meta:
# verbose_name = "Car Trim"
@admin.register(models.CarSpecification)
class CarSpecificationAdmin(admin.ModelAdmin):
list_display = ('name', 'arabic_name', 'id_parent')
search_fields = ('name', 'id_parent')
list_filter = ('id_parent',)
class Meta:
verbose_name = "Car Specification"
@admin.register(models.CarOption)
class CarOptionAdmin(admin.ModelAdmin):
list_display = ('name', 'arabic_name', 'id_parent')
search_fields = ('name', 'id_parent')
# list_filter = ('id_parent',)
class Meta:
verbose_name = "Car Option"
# @admin.register(models.UserActivityLog)
# class UserActivityLogAdmin(admin.ModelAdmin):
# list_display = ('user', 'action', 'timestamp')
# search_fields = ('user__username', 'action')
# list_filter = ('timestamp',)
@admin.register(ledger_models.ItemTransactionModel)
class ItemTransactionModelAdmin(admin.ModelAdmin):
actions = [export_to_pdf_landscape, export_to_pdf_portrait]

11
inventory/apps.py Normal file
View File

@ -0,0 +1,11 @@
from django.apps import AppConfig
class InventoryConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'inventory'
def ready(self):
import inventory.signals
from decimal import Decimal
from inventory.models import VatRate
VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True)

View File

@ -0,0 +1,15 @@
from django.conf import settings
def currency_context(request):
return {
'CURRENCY': settings.CURRENCY
}
def breadcrumbs(request):
breadcrumbs = []
path = request.path.strip('/').split('/')
for i in range(len(path)):
url = '/' + '/'.join(path[:i+1]) + '/'
breadcrumbs.append({'name': path[i].capitalize(), 'url': url})
return {'breadcrumbs': breadcrumbs}

BIN
inventory/data/.DS_Store vendored Normal file

Binary file not shown.

7
inventory/filters.py Normal file
View File

@ -0,0 +1,7 @@
from django_ledger.models import AccountModel
import django_filters
class AccountModelFilter(django_filters.FilterSet):
class Meta:
model = AccountModel
fields = ['code', 'name','role']

964
inventory/forms.py Normal file
View File

@ -0,0 +1,964 @@
from django.core.cache import cache
from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group
from appointment.models import Appointment, Service, StaffMember
from django.urls import reverse
from django_countries.widgets import CountrySelectWidget
from django_ledger.models import CustomerModel
from phonenumber_field.formfields import PhoneNumberField
from django.core.validators import MinLengthValidator
from django.core.validators import RegexValidator
from django import forms
from django.contrib.auth import get_user_model
from phonenumber_field.phonenumber import PhoneNumber
from .models import CustomGroup, Status, Stage
from .mixins import AddClassMixin
from django.forms.models import inlineformset_factory
from django_ledger.forms.invoice import (
InvoiceModelCreateForm as InvoiceModelCreateFormBase,
)
from django_ledger.forms.estimate import (
EstimateModelCreateForm as EstimateModelCreateFormBase,
)
# from django_ledger.forms.ledger import LedgerModelCreateForm as LedgerModelCreateFormBase
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
from django_ledger.forms.journal_entry import JournalEntryModelCreateForm as JournalEntryModelCreateFormBase
from .models import (
Dealer,
DealersMake,
# Branch,
Vendor,
Schedule,
Customer,
Car,
CarTransfer,
CarFinance,
CustomCard,
CarRegistration,
CarColors,
ExteriorColors,
InteriorColors,
# SaleQuotation,
CarLocation,
Representative,
# SaleQuotationCar,
AdditionalServices,
Staff,
Opportunity,
Lead,
Activity,
Notes,
CarModel,
SaleOrder,
CarMake,
DealerSettings
)
from django_ledger import models as ledger_models
from django.forms import (
DateInput,
DateTimeInput,
)
from django.utils.translation import gettext_lazy as _
import django_tables2 as tables
from django.forms import formset_factory
User = get_user_model()
class AdditionalServiceForm(forms.ModelForm):
class Meta:
model = AdditionalServices
fields = ["name", "price", "description", "taxable", "uom"]
# class PaymentForm(forms.ModelForm):
# invoice = forms.ModelChoiceField(queryset=InvoiceModel.objects.all(),label="Invoice", required=True)
# class Meta:
# model = Payment
# fields = ['amount','payment_method', 'reference_number']
class StaffForm(forms.ModelForm):
email = forms.EmailField(
required=True,
label="Email",
widget=forms.EmailInput(attrs={"class": "form-control form-control-sm"}),
)
service_offered = forms.ModelMultipleChoiceField(
label="Services Offered",
widget=forms.CheckboxSelectMultiple(attrs={"class": "form-check-input"}),
queryset=Service.objects.all(),
required=False,)
class Meta:
model = Staff
fields = ["name", "arabic_name", "phone_number", "staff_type"]
# def __init__(self, *args, **kwargs):
# user_instance = kwargs.get("instance")
# if user_instance and user_instance.user:
# initial = kwargs.setdefault("initial", {})
# initial["email"] = user_instance.user.email
# super().__init__(*args, **kwargs)
#
# def save(self, commit=True):
# user_instance = super().save(commit=False)
# user = user_instance.user
# user.email = self.cleaned_data["email"]
# if commit:
# user.save()
# user_instance.save()
# return user_instance
# Dealer Form
class DealerForm(forms.ModelForm):
class Meta:
model = Dealer
fields = [
"name",
"arabic_name",
"crn",
"vrn",
"phone_number",
"address",
"logo",
]
class CustomerForm(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
arabic_name = forms.CharField()
email = forms.EmailField()
phone_number = PhoneNumberField(region="SA")
national_id = forms.CharField(max_length=10,required=False)
crn = forms.CharField(required=False)
vrn = forms.CharField(required=False)
address = forms.CharField()
class OrganizationForm(CustomerForm):
contact_person = forms.CharField(required=False)
logo = forms.ImageField(required=False)
# class CustomerForm(forms.ModelForm, AddClassMixin):
# class Meta:
# model = Customer
# fields = [
# "title",
# "first_name",
# "middle_name",
# "last_name",
# "gender",
# "dob",
# "email",
# "national_id",
# "phone_number",
# "address",
# ]
# widgets = {
# "phone_number": forms.TextInput(attrs={"class": "phone"}),
# "dob": forms.DateInput(attrs={"type": "date"}),
# }
class CarForm(
forms.ModelForm,
AddClassMixin,
):
class Meta:
model = Car
fields = [
"vin",
"id_car_make",
"id_car_model",
"year",
"id_car_serie",
"id_car_trim",
"stock_type",
"remarks",
"mileage",
"receiving_date",
"vendor",
]
widgets = {
"id_car_make": forms.Select(attrs={"class": "form-select form-select-sm"}),
"receiving_date": forms.DateTimeInput(attrs={"type": "datetime-local"}),
"remarks": forms.Textarea(attrs={"rows": 2}),
}
def __init__(self, *args, **kwargs):
dealer = kwargs.pop("dealer", None)
super().__init__(*args, **kwargs)
if "id_car_make" in self.fields:
queryset = self.fields["id_car_make"].queryset.filter(is_sa_import=True)
self.fields["id_car_make"].choices = [
(obj.id_car_make, obj.get_local_name()) for obj in queryset
]
if "id_car_model" in self.fields:
queryset = self.fields["id_car_model"].queryset
self.fields["id_car_model"].choices = [
(obj.id_car_model, obj.get_local_name()) for obj in queryset
]
if "vendor" in self.fields:
self.fields["vendor"].queryset = ledger_models.VendorModel.objects.filter(
active=True
)
# queryset = self.fields["vendor"].queryset
# self.fields["vendor"].choices = [
# (obj.pk, obj.get_local_name()) for obj in queryset
# ]
class CarUpdateForm(forms.ModelForm, AddClassMixin):
class Meta:
model = Car
fields = [
"vendor",
"status",
"stock_type",
"mileage",
"receiving_date",
"remarks",
]
widgets = {
"receiving_date": forms.DateTimeInput(attrs={"type": "datetime-local"}),
"remarks": forms.Textarea(attrs={"rows": 2}),
}
def __init__(self, *args, **kwargs):
dealer = kwargs.pop("dealer", None)
super().__init__(*args, **kwargs)
# if dealer and 'branch' in self.fields:
# self.fields['branch'].queryset = Branch.objects.filter(dealer=dealer)
# self.fields['branch'].choices = [
# (branch.id, branch.get_local_name()) for branch in self.fields['branch'].queryset
# ]
# if "vendor" in self.fields:
# queryset = self.fields["vendor"].queryset
# if queryset:
# self.fields["vendor"].choices = [
# (vendor.id, vendor.get_local_name()) for vendor in queryset
# ]
class CarFinanceForm(forms.ModelForm):
additional_finances = forms.ModelMultipleChoiceField(
queryset=AdditionalServices.objects.all(),
widget=forms.CheckboxSelectMultiple(attrs={"class": "form-check-input"}),
required=False,
)
class Meta:
model = CarFinance
exclude = [
"car",
"profit_margin",
"vat_amount",
"total",
"additional_services",
]
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
# if self.instance.pk:
# self.fields[
# "additional_finances"
# ].initial = self.instance.additional_services.all()
def save(self, commit=True):
instance = super().save()
instance.additional_services.set(self.cleaned_data["additional_finances"])
instance.save()
return instance
class CarLocationForm(forms.ModelForm):
class Meta:
model = CarLocation
fields = ["showroom", "description"]
widgets = {
"description": forms.Textarea(attrs={"rows": 2, "class": "form-control"}),
}
class CarTransferForm(forms.ModelForm):
class Meta:
model = CarTransfer
fields = ["car", "to_dealer", "remarks"]
widgets = {
"remarks": forms.Textarea(attrs={"rows": 2, "class": "form-control"}),
}
# Custom Card Form
class CustomCardForm(forms.ModelForm):
custom_date = forms.DateTimeField(
widget=forms.DateInput(attrs={"type": "date"}),
label=_("Custom Date"),
)
class Meta:
model = CustomCard
fields = ["custom_number", "custom_date"]
# Car Registration Form
class CarRegistrationForm(forms.ModelForm):
class Meta:
model = CarRegistration
fields = ["plate_number", "text1", "text2", "text3", "registration_date"]
widgets = {
"registration_date": forms.DateTimeInput(attrs={"type": "datetime-local"}),
}
# class VendorForm(VendorModelForm):
# pass
class VendorForm(forms.ModelForm):
class Meta:
model = Vendor
fields = [
"name",
"arabic_name",
"crn",
"vrn",
"email",
"phone_number",
"contact_person",
"address",
"logo",
]
class CarColorsForm(forms.ModelForm):
class Meta:
model = CarColors
fields = ["exterior", "interior"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["exterior"].queryset = ExteriorColors.objects.all()
self.fields["exterior"].widget = forms.RadioSelect(
attrs={"class": "form-check-input"}
)
self.fields["exterior"].choices = [
(color.id, f"{color.get_local_name}")
for color in ExteriorColors.objects.all().order_by("-name")
]
self.fields["interior"].queryset = InteriorColors.objects.all()
self.fields["interior"].widget = forms.RadioSelect(
attrs={"class": "form-check-input"}
)
self.fields["interior"].choices = [
(color.id, f"{color.get_local_name}")
for color in InteriorColors.objects.all().order_by("-name")
]
def clean(self):
cleaned_data = super().clean()
exterior = cleaned_data.get("exterior")
interior = cleaned_data.get("interior")
if not exterior or not interior:
raise forms.ValidationError(
_("Both exterior and interior colors must be selected.")
)
return cleaned_data
# class QuotationForm(forms.ModelForm):
# cars = ModelMultipleChoiceField(
# queryset=Car.objects.none(), # Default empty queryset
# widget=forms.CheckboxSelectMultiple,
# label="Select Cars",
# )
#
# class Meta:
# model = SaleQuotation
# fields = ["customer", "cars", "remarks"]
#
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
#
# 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"
class WizardForm1(forms.Form):
hx_attrs = {
"hx-post":"",
"hx-target": "#wizardValidationForm1",
"hx-select": "#wizardValidationForm1",
"hx-trigger": "blur delay:500ms",
"hx-swap": "innerHTML",
}
email = forms.EmailField(
label=_("Email Address"),
widget=forms.EmailInput(
attrs={
"class": "form-control form-control-sm email",
"placeholder": _("Email address"),
"name": _("email"),
"required": "required",
# **hx_attrs
}
),
error_messages={
"required": _("You must add an email."),
},
)
password = forms.CharField(
label=_("Password"),
widget=forms.PasswordInput(
attrs={
"class": "form-control form-control-sm",
"placeholder": _("Password"),
"required": "required",
# **hx_attrs
},
render_value=True
),
error_messages={
"required": _("This field is required."),
},
min_length=8,
)
confirm_password = forms.CharField(
label=_("Confirm Password"),
widget=forms.PasswordInput(
attrs={
"class": "form-control form-control-sm",
"placeholder": _("Confirm Password"),
"required": "required",
# **hx_attrs
},
render_value=True
),
error_messages={
"required": _("This field is required."),
},
min_length=8,
)
terms = forms.BooleanField(
label=_("I accept the Terms and Privacy Policy"),
widget=forms.CheckboxInput(
attrs={
"class": "form-check-input",
"required": "required",
# **hx_attrs
}
),
error_messages={
"required": _("You must accept the terms and privacy policy."),
},
)
def clean_email(self):
email = self.cleaned_data.get("email")
if email:
if User.objects.filter(email=email).exists():
raise forms.ValidationError(
_("An account with this email already exists.")
)
return email
def clean_confirm_password(self):
password = self.cleaned_data.get("password")
confirm_password = self.cleaned_data.get("confirm_password")
if password and confirm_password and password != confirm_password:
raise forms.ValidationError(_("Passwords do not match."))
return confirm_password
class WizardForm2(forms.Form):
name = forms.CharField(
label=_("Name"),
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"placeholder": _("English Name"),
"required": "required",
}
),
error_messages={
"required": _("Please enter an English Name."),
},
)
arabic_name = forms.CharField(
label=_("Arabic Name"),
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"placeholder": _("Arabic Name"),
"required": "required",
}
),
error_messages={
"required": _("Please enter an Arabic name."),
},
)
phone_number = PhoneNumberField(
label=_("Phone Number"),
widget=forms.TextInput(
attrs={
"placeholder": _("Phone"),
}
),
region="SA",
error_messages={
"required": _("This field is required."),
"invalid": _("Phone number must be in the format 05xxxxxxxx"),
},
required=True,
)
class WizardForm3(forms.Form):
# CRN field with max length of 10
crn = forms.CharField(
label=_("CRN"),
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"placeholder": _("Commercial Registration Number"),
"required": "required",
"maxlength": "10",
}
),
max_length=10,
error_messages={
"required": _("This field is required."),
"max_length": "Commercial Registration Number must be 10 characters.",
},
)
# VRN field with max length of 15
vrn = forms.CharField(
label=_("VRN"),
widget=forms.TextInput(
attrs={
"class": "form-control form-control-sm",
"placeholder": _("VAT Registration Number"),
"required": "required",
"maxlength": "15",
}
),
max_length=15, #
error_messages={
"required": _("This field is required."),
"max_length": _("VAT Registration Number must be 15 characters."),
},
)
address = forms.CharField(
label=_("Address"),
widget=forms.Textarea(
attrs={
"class": "form-control form-control-sm",
"rows": "3",
"required": "required",
}
),
error_messages={
"required": _("This field is required."),
},
)
# def clean(self):
# cleaned_data = super().clean()
# password = cleaned_data.get("password")
# confirm_password = cleaned_data.get("confirm_password")
# if password != confirm_password:
# raise forms.ValidationError("Passwords do not match.")
# else:
# return cleaned_data
class ItemForm(forms.Form):
item = forms.ModelChoiceField(
queryset=ledger_models.ItemModel.objects.all(),
label="Item",
required=True,
validators=[MinLengthValidator(5)],
)
quantity = forms.DecimalField(label="Quantity", required=True)
# unit = forms.DecimalField(label="Unit", required=True)
# unit_cost = forms.DecimalField(label="Unit Cost", required=True)
# unit_sales_price = forms.DecimalField(label="Unit Sales Price", required=True)
class PaymentForm(forms.Form):
invoice = forms.ModelChoiceField(
queryset=ledger_models.InvoiceModel.objects.all(),
label="Invoice",
required=False,
)
bill = forms.ModelChoiceField(
queryset=ledger_models.BillModel.objects.all(), label="Bill", required=False
)
amount = forms.DecimalField(label="Amount", required=True)
payment_method = forms.ChoiceField(
choices=[
("cash", _("cash")),
("credit", _("credit")),
("transfer", _("transfer")),
("debit", _("debit")),
("SADAD", _("SADAD")),
],
label="Payment Method",
required=True,
)
payment_date = forms.DateField(
label="Payment Date", widget=DateInput(attrs={"type": "date"}), required=True
)
def clean_amount(self):
invoice = self.cleaned_data["invoice"]
bill = self.cleaned_data["bill"]
model = invoice if invoice else bill
amount = self.cleaned_data["amount"]
if amount + model.amount_paid > model.amount_due:
raise forms.ValidationError("Payment amount is greater than amount due")
if amount <= 0:
raise forms.ValidationError("Payment amount must be greater than 0")
if model.is_paid():
raise forms.ValidationError("Invoice is already paid")
if amount > model.amount_due:
raise forms.ValidationError("Payment amount is greater than amount due")
return amount
class EmailForm(forms.Form):
subject = forms.CharField(max_length=255)
message = forms.CharField(widget=forms.Textarea)
from_email = forms.EmailField()
to_email = forms.EmailField(label="To")
class LeadForm(forms.ModelForm):
id_car_make = forms.ModelChoiceField(
label="Make",
queryset=CarMake.objects.filter(is_sa_import=True),
widget=forms.Select(
attrs={
"class": "form-control form-control-sm",
"hx-get": "",
"hx-include": "#id_id_car_make",
"hx-select": "#div_id_id_car_model",
"hx-target": "#div_id_id_car_model",
"hx-swap": "outerHTML",
"hx-on::before-request": "document.querySelector('#id_id_car_model').setAttribute('disabled', true)",
"hx-on::after-request": "document.querySelector('#id_id_car_model').removeAttribute('disabled')",
}
),
required=True,
)
id_car_model = forms.ModelChoiceField(
label="Model",
queryset=CarModel.objects.none(),
widget=forms.Select(attrs={"class": "form-control form-control-sm"}),
required=True,
)
class Meta:
model = Lead
fields = [
"first_name",
"last_name",
"email",
"phone_number",
"lead_type",
"address",
"id_car_make",
"id_car_model",
"crn",
"vrn",
"year",
"source",
"channel",
"staff",
"priority",
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if "id_car_make" in self.fields:
queryset = self.fields["id_car_make"].queryset.filter(is_sa_import=True)
self.fields["id_car_make"].choices = [
(obj.id_car_make, obj.get_local_name()) for obj in queryset
]
class ScheduleForm(forms.ModelForm):
scheduled_at = forms.DateTimeField(
widget=DateTimeInput(attrs={"type": "datetime-local"})
)
class Meta:
model = Schedule
fields = ["purpose", "scheduled_type", "scheduled_at", "duration", "notes",]
class NoteForm(forms.ModelForm):
class Meta:
model = Notes
fields = ["note"]
class ActivityForm(forms.ModelForm):
class Meta:
model = Activity
fields = ["activity_type", "notes"]
class OpportunityForm(forms.ModelForm):
class Meta:
model = Opportunity
fields = ["customer", "car", "stage", "probability", "staff", "closing_date"]
class InvoiceModelCreateForm(InvoiceModelCreateFormBase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["cash_account"].widget = forms.HiddenInput()
self.fields["prepaid_account"].widget = forms.HiddenInput()
self.fields["unearned_account"].widget = forms.HiddenInput()
self.fields["date_draft"] = forms.DateField(
widget=DateInput(attrs={"type": "date"})
)
def get_customer_queryset(self):
if "customer" in self.fields:
self.fields[
"customer"
].queryset = self.USER_MODEL.dealer.entity.get_customers()
class BillModelCreateForm(BillModelCreateFormBase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["cash_account"].widget = forms.HiddenInput()
self.fields["prepaid_account"].widget = forms.HiddenInput()
self.fields["unearned_account"].widget = forms.HiddenInput()
# self.fields["date_draft"] = forms.DateField(
# widget=DateInput(attrs={"type": "date"})
# )
class SaleOrderForm(forms.ModelForm):
class Meta:
model = SaleOrder
fields = ["estimate", "payment_method", "comments"]
widgets = {
"comments": forms.Textarea(attrs={"rows": 3}),
}
class EstimateModelCreateForm(EstimateModelCreateFormBase):
class Meta:
model = ledger_models.EstimateModel
fields = ["title","customer", "terms"]
widgets = {
"customer": forms.Select(
attrs={
"id": "djl-customer-estimate-customer-input",
"class": "input",
"label": _("Customer"),
}
),
'terms': forms.Select(attrs={
'id': 'djl-customer-estimate-terms-input',
'class': 'input',
'label': _('Terms'),
}),
'title': forms.TextInput(attrs={
'id': 'djl-customer-job-title-input',
'class': 'input' + ' is-large',
'label': _('Title'),
})
}
labels = {
'title': _('Title'),
'terms': _('Terms'),
"customer": _("Customer"),
}
def __init__(self, *args, entity_slug, user_model, **kwargs):
super(EstimateModelCreateForm, self).__init__(
*args, entity_slug=entity_slug, user_model=user_model, **kwargs
)
self.ENTITY_SLUG = entity_slug
self.USER_MODEL = user_model
self.fields["customer"].queryset = self.get_customer_queryset()
def get_customer_queryset(self):
return self.USER_MODEL.dealer.entity.get_customers()
class OpportunityStatusForm(forms.Form):
status = forms.ChoiceField(
label="Status",
choices=Status.choices,
widget=forms.Select(
attrs={
"class": "form-control form-control-sm",
"hx-get": "{% url 'opportunity_update_status' opportunity.id %}",
"hx-target": ".other-information",
"hx-select": ".other-information",
"hx-swap": "outerHTML",
"hx-on::after-request": "this.setAttribute('disabled','true')",
"disabled": "disabled",
}
),
required=True,
)
stage = forms.ChoiceField(
label="Stage",
choices=Stage.choices,
widget=forms.Select(
attrs={
"class": "form-control form-control-sm",
"hx-target": ".other-information",
"hx-select": ".other-information",
"hx-swap": "outerHTML",
"hx-on::after-request": "this.setAttribute('disabled','true')",
"disabled": "disabled",
}
),
required=True,
)
class GroupForm(forms.ModelForm):
class Meta:
model = CustomGroup
fields = ["name"]
class PermissionForm(forms.ModelForm):
name = forms.ModelMultipleChoiceField(
queryset=cache.get('permissions_queryset', Permission.objects.filter(content_type__app_label__in=["inventory","django_ledger"])),
widget=forms.CheckboxSelectMultiple(),
required=True
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
cache.set('permissions_queryset', Permission.objects.filter(content_type__app_label__in=["inventory","django_ledger"]), 60*60)
class Meta:
model = Permission
fields = ["name"]
class UserGroupForm(forms.ModelForm):
name = forms.ModelMultipleChoiceField(
queryset= CustomGroup.objects.all(),
widget=forms.CheckboxSelectMultiple(),
required=True
)
class Meta:
model = CustomGroup
fields = ["name"]
class DealerSettingsForm(forms.ModelForm):
class Meta:
model = DealerSettings
fields = "__all__"
class LeadTransferForm(forms.Form):
transfer_to = forms.ModelChoiceField(label="to",queryset=Staff.objects.all())
class DealersMakeForm(forms.Form):
car_makes = forms.ModelMultipleChoiceField(
queryset=CarMake.objects.filter(is_sa_import=True),
widget=forms.CheckboxSelectMultiple(attrs={"class": "car-makes-grid"}),
required=True,
label=_("Select Car Makes")
)
def __init__(self, *args, **kwargs):
self.dealer = kwargs.pop("dealer", None) # Pass dealer instance
super().__init__(*args, **kwargs)
def save(self):
if self.dealer:
DealersMake.objects.filter(dealer=self.dealer).delete()
for car_make in self.cleaned_data["car_makes"]:
DealersMake.objects.create(dealer=self.dealer, car_make=car_make)
class JournalEntryModelCreateForm(JournalEntryModelCreateFormBase):
pass
# class LedgerModelCreateForm(LedgerModelCreateFormBase):
# pass

1854
inventory/haikalna.py Normal file

File diff suppressed because it is too large Load Diff

BIN
inventory/management/.DS_Store vendored Normal file

Binary file not shown.

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