Revert "fixup! update"

This reverts commit 5e5eec299a4432784a9114264f6e7d39402a9812.
This commit is contained in:
Marwan Alwali 2025-03-14 02:12:50 +03:00
parent 5e5eec299a
commit e9c9445377
105 changed files with 19579836 additions and 7078 deletions

4
.gitignore vendored
View File

@ -4,16 +4,12 @@
*.pyc *.pyc
__pycache__ __pycache__
**/*__pycache__ **/*__pycache__
**/*/__pycache__
inventory/__pycache__
db.sqlite db.sqlite
db.sqlite3 db.sqlite3
db.sqlite3.backup db.sqlite3.backup
db.sqlite* db.sqlite*
media media
car*.json
car_inventory/settings.py car_inventory/settings.py
car_inventory/__pycache__
scripts/dsrpipe.py scripts/dsrpipe.py
# Backup files # # Backup files #
*.bak *.bak

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

View File

@ -1,6 +1,5 @@
# Generated by Django 5.1.6 on 2025-03-06 01:43 # Generated by Django 5.1.5 on 2025-01-30 11:28
import datetime
import django.db.models.deletion import django.db.models.deletion
import inventory.mixins import inventory.mixins
import inventory.models import inventory.models
@ -15,12 +14,8 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('appointment', '__first__'),
('auth', '0012_alter_user_first_name_max_length'),
('contenttypes', '0002_remove_content_type_name'), ('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
migrations.swappable_dependency(settings.DJANGO_LEDGER_ACCOUNT_MODEL),
migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL),
migrations.swappable_dependency(settings.DJANGO_LEDGER_ENTITY_MODEL), migrations.swappable_dependency(settings.DJANGO_LEDGER_ENTITY_MODEL),
migrations.swappable_dependency(settings.DJANGO_LEDGER_ESTIMATE_MODEL), migrations.swappable_dependency(settings.DJANGO_LEDGER_ESTIMATE_MODEL),
migrations.swappable_dependency(settings.DJANGO_LEDGER_INVOICE_MODEL), migrations.swappable_dependency(settings.DJANGO_LEDGER_INVOICE_MODEL),
@ -99,6 +94,25 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'payments', 'verbose_name_plural': 'payments',
}, },
), ),
migrations.CreateModel(
name='SubscriptionPlan',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Name of the subscription plan', max_length=100, unique=True)),
('description', models.TextField()),
('price', models.DecimalField(decimal_places=2, max_digits=10)),
('max_users', models.PositiveIntegerField(default=1, help_text='Maximum number of users allowed')),
('max_inventory_size', models.PositiveIntegerField(default=50, help_text='Maximum number of cars in inventory')),
('support_level', models.CharField(choices=[('basic', 'Basic Support'), ('priority', 'Priority Support'), ('dedicated', 'Dedicated Support')], default='basic', help_text='Level of support provided', max_length=50)),
('custom_features', models.JSONField(blank=True, help_text='Additional features specific to this plan', null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'verbose_name': 'Subscription Plan',
'verbose_name_plural': 'Subscription Plans',
},
),
migrations.CreateModel( migrations.CreateModel(
name='VatRate', name='VatRate',
fields=[ fields=[
@ -108,6 +122,23 @@ class Migration(migrations.Migration):
('created_at', models.DateTimeField(auto_now_add=True)), ('created_at', models.DateTimeField(auto_now_add=True)),
], ],
), ),
migrations.CreateModel(
name='Activity',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.PositiveIntegerField()),
('activity_type', models.CharField(choices=[('call', 'Call'), ('sms', 'SMS'), ('email', 'Email'), ('whatsapp', 'WhatsApp'), ('visit', 'Visit'), ('add_car', 'Add Car'), ('reserve_car', 'Reserve Car'), ('remove_car', 'Remove Car'), ('create_quotation', 'Create Quotation'), ('cancel_quotation', 'Cancel Quotation'), ('create_order', 'Create Order'), ('cancel_order', 'Cancel Order'), ('create_invoice', 'Create Invoice'), ('cancel_invoice', 'Cancel Invoice')], max_length=50, verbose_name='Activity Type')),
('notes', models.TextField(blank=True, null=True, verbose_name='Notes')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='activities_created', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Activity',
'verbose_name_plural': 'Activities',
},
),
migrations.CreateModel( migrations.CreateModel(
name='AdditionalServices', name='AdditionalServices',
fields=[ fields=[
@ -137,7 +168,6 @@ class Migration(migrations.Migration):
('remarks', models.TextField(blank=True, null=True, verbose_name='Remarks')), ('remarks', models.TextField(blank=True, null=True, verbose_name='Remarks')),
('mileage', models.IntegerField(blank=True, null=True, verbose_name='Mileage')), ('mileage', models.IntegerField(blank=True, null=True, verbose_name='Mileage')),
('receiving_date', models.DateTimeField(verbose_name='Receiving Date')), ('receiving_date', models.DateTimeField(verbose_name='Receiving Date')),
('hash', models.CharField(blank=True, max_length=64, null=True, verbose_name='Hash')),
('vendor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to=settings.DJANGO_LEDGER_VENDOR_MODEL, verbose_name='Vendor')), ('vendor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to=settings.DJANGO_LEDGER_VENDOR_MODEL, verbose_name='Vendor')),
('id_car_make', models.ForeignKey(blank=True, db_column='id_car_make', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make')), ('id_car_make', models.ForeignKey(blank=True, db_column='id_car_make', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make')),
], ],
@ -212,10 +242,10 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('plate_number', models.IntegerField(verbose_name='Plate Number')), ('plate_number', models.IntegerField(verbose_name='Plate Number')),
('text1', models.CharField(max_length=1, verbose_name='Text 1')), ('text1', models.CharField(max_length=1, verbose_name='Text 1')),
('text2', models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 2')), ('text2', models.CharField(max_length=1, verbose_name='Text 2')),
('text3', models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 3')), ('text3', models.CharField(max_length=1, verbose_name='Text 3')),
('registration_date', models.DateTimeField(verbose_name='Registration Date')), ('registration_date', models.DateTimeField(verbose_name='Registration Date')),
('car', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='registrations', to='inventory.car', verbose_name='Car')), ('car', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='registrations', to='inventory.car', verbose_name='Car')),
], ],
options={ options={
'verbose_name': 'Registration', 'verbose_name': 'Registration',
@ -332,15 +362,6 @@ class Migration(migrations.Migration):
('objects', inventory.models.DealerUserManager()), ('objects', inventory.models.DealerUserManager()),
], ],
), ),
migrations.CreateModel(
name='CustomGroup',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.group', verbose_name='')),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='groups', to='inventory.dealer')),
],
),
migrations.CreateModel( migrations.CreateModel(
name='Customer', name='Customer',
fields=[ fields=[
@ -357,7 +378,6 @@ class Migration(migrations.Migration):
('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')), ('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='customer_profile', to=settings.AUTH_USER_MODEL)),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customers', to='inventory.dealer')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customers', to='inventory.dealer')),
], ],
options={ options={
@ -412,78 +432,19 @@ class Migration(migrations.Migration):
name='dealer', name='dealer',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.dealer', verbose_name='Dealer'), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.dealer', verbose_name='Dealer'),
), ),
migrations.CreateModel(
name='Activity',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.PositiveIntegerField()),
('activity_type', models.CharField(choices=[('call', 'Call'), ('sms', 'SMS'), ('email', 'Email'), ('whatsapp', 'WhatsApp'), ('visit', 'Visit'), ('add_car', 'Add Car'), ('sale_car', 'Sale Car'), ('reserve_car', 'Reserve Car'), ('transfer_car', 'Transfer Car'), ('remove_car', 'Remove Car'), ('create_quotation', 'Create Quotation'), ('cancel_quotation', 'Cancel Quotation'), ('create_order', 'Create Order'), ('cancel_order', 'Cancel Order'), ('create_invoice', 'Create Invoice'), ('cancel_invoice', 'Cancel Invoice')], max_length=50, verbose_name='Activity Type')),
('notes', models.TextField(blank=True, null=True, verbose_name='Notes')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='contenttypes.contenttype')),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='activities_created_by', to=settings.AUTH_USER_MODEL)),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='inventory.dealer')),
],
options={
'verbose_name': 'Activity',
'verbose_name_plural': 'Activities',
},
),
migrations.CreateModel(
name='DealerSettings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('additional_info', models.JSONField(blank=True, default=dict, null=True)),
('bill_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_cash', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('bill_prepaid_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('bill_unearned_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_unearned', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('dealer', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='settings', to='inventory.dealer')),
('invoice_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_cash', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('invoice_prepaid_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('invoice_unearned_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_unearned', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
],
),
migrations.CreateModel(
name='Email',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.PositiveIntegerField()),
('from_email', models.TextField(blank=True, null=True, verbose_name='From Email')),
('to_email', models.TextField(blank=True, null=True, verbose_name='To Email')),
('subject', models.TextField(blank=True, null=True, verbose_name='Subject')),
('message', models.TextField(blank=True, null=True, verbose_name='Message')),
('status', models.CharField(choices=[('SENT', 'Sent'), ('FAILED', 'Failed'), ('DELIVERED', 'Delivered'), ('OPEN', 'Open'), ('DRAFT', 'Draft')], default='OPEN', max_length=20, verbose_name='Status')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='emails_created', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Email',
'verbose_name_plural': 'Emails',
},
),
migrations.CreateModel( migrations.CreateModel(
name='Lead', name='Lead',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('first_name', models.CharField(max_length=50, verbose_name='First Name')),
('last_name', models.CharField(max_length=50, verbose_name='Last Name')),
('email', models.EmailField(max_length=254, verbose_name='Email')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')),
('lead_type', models.CharField(choices=[('customer', 'Customer'), ('organization', 'Organization')], default='customer', max_length=50, verbose_name='Lead Type')),
('year', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Year')), ('year', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Year')),
('source', models.CharField(choices=[('referrals', 'Referrals'), ('whatsapp', 'WhatsApp'), ('showroom', 'Showroom'), ('tiktok', 'TikTok'), ('instagram', 'Instagram'), ('x', 'X'), ('facebook', 'Facebook'), ('motory', 'Motory'), ('influencers', 'Influencers'), ('youtube', 'Youtube'), ('campaign', 'Campaign')], max_length=50, verbose_name='Source')), ('source', models.CharField(choices=[('referrals', 'Referrals'), ('whatsapp', 'WhatsApp'), ('showroom', 'Showroom'), ('tiktok', 'TikTok'), ('instagram', 'Instagram'), ('x', 'X'), ('facebook', 'Facebook'), ('motory', 'Motory'), ('influencers', 'Influencers'), ('youtube', 'Youtube'), ('campaign', 'Campaign')], max_length=50, verbose_name='Source')),
('channel', models.CharField(choices=[('walk_in', 'Walk In'), ('toll_free', 'Toll Free'), ('website', 'Website'), ('email', 'Email'), ('form', 'Form')], max_length=50, verbose_name='Channel')), ('channel', models.CharField(choices=[('walk_in', 'Walk In'), ('toll_free', 'Toll Free'), ('website', 'Website'), ('email', 'Email'), ('form', 'Form')], max_length=50, verbose_name='Channel')),
('crn', models.CharField(blank=True, max_length=10, null=True, unique=True, verbose_name='Commercial Registration Number')), ('city', models.CharField(max_length=50, verbose_name='City')),
('vrn', models.CharField(blank=True, max_length=15, null=True, unique=True, verbose_name='VAT Registration Number')),
('address', models.CharField(max_length=50, verbose_name='address')),
('priority', models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High')], default='medium', max_length=10, verbose_name='Priority')), ('priority', models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High')], default='medium', max_length=10, verbose_name='Priority')),
('status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], db_index=True, default='new', max_length=50, verbose_name='Status')), ('status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('canceled', 'Canceled')], db_index=True, default='new', max_length=50, verbose_name='Status')),
('created', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Created')), ('created', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='leads', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL)), ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='inventory.customer')),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='inventory.dealer')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='inventory.dealer')),
('id_car_make', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make')), ('id_car_make', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make')),
('id_car_model', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel', verbose_name='Model')), ('id_car_model', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel', verbose_name='Model')),
@ -593,26 +554,6 @@ class Migration(migrations.Migration):
'ordering': ['-created'], 'ordering': ['-created'],
}, },
), ),
migrations.CreateModel(
name='Schedule',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('purpose', models.CharField(choices=[('Product Demo', 'Product Demo'), ('Follow-Up Call', 'Follow-Up Call'), ('Contract Discussion', 'Contract Discussion'), ('Sales Meeting', 'Sales Meeting'), ('Support Call', 'Support Call'), ('Other', 'Other')], max_length=200)),
('scheduled_at', models.DateTimeField()),
('scheduled_type', models.CharField(choices=[('Call', 'Call'), ('Meeting', 'Meeting'), ('Email', 'Email')], default='Call', max_length=200)),
('duration', models.DurationField(default=datetime.timedelta(seconds=300))),
('notes', models.TextField(blank=True, null=True)),
('status', models.CharField(choices=[('Scheduled', 'Scheduled'), ('Completed', 'Completed'), ('Canceled', 'Canceled')], default='Scheduled', max_length=200)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL)),
('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='inventory.lead')),
('scheduled_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['-scheduled_at'],
},
),
migrations.CreateModel( migrations.CreateModel(
name='Staff', name='Staff',
fields=[ fields=[
@ -620,11 +561,11 @@ class Migration(migrations.Migration):
('name', models.CharField(max_length=255, verbose_name='Name')), ('name', models.CharField(max_length=255, verbose_name='Name')),
('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')), ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')),
('staff_type', models.CharField(choices=[('inventory', 'Inventory'), ('accountant', 'Accountant'), ('sales', 'Sales')], max_length=255, verbose_name='Staff Type')), ('staff_type', models.CharField(choices=[('manager', 'Manager'), ('inventory', 'Inventory'), ('accountant', 'Accountant'), ('sales', 'Sales'), ('coordinator', 'Coordinator'), ('receptionist', 'Receptionist'), ('agent', 'Agent')], max_length=255, verbose_name='Staff Type')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to='inventory.dealer')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to='inventory.dealer')),
('staff_member', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to='appointment.staffmember')), ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to=settings.AUTH_USER_MODEL)),
], ],
options={ options={
'verbose_name': 'Staff', 'verbose_name': 'Staff',
@ -641,17 +582,15 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('stage', models.CharField(choices=[('prospect', 'Prospect'), ('proposal', 'Proposal'), ('negotiation', 'Negotiation'), ('closed_won', 'Closed Won'), ('closed_lost', 'Closed Lost')], max_length=20, verbose_name='Stage')), ('stage', models.CharField(choices=[('prospect', 'Prospect'), ('proposal', 'Proposal'), ('negotiation', 'Negotiation'), ('closed_won', 'Closed Won'), ('closed_lost', 'Closed Lost')], max_length=20, verbose_name='Stage')),
('status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], default='new', max_length=20, verbose_name='Status')), ('status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('canceled', 'Canceled')], default='new', max_length=20, verbose_name='Status')),
('probability', models.PositiveIntegerField(validators=[inventory.models.validate_probability])), ('probability', models.PositiveIntegerField(validators=[inventory.models.validate_probability])),
('closing_date', models.DateField(blank=True, null=True, verbose_name='Closing Date')), ('closing_date', models.DateField(verbose_name='Closing Date')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('closed', models.BooleanField(default=False, verbose_name='Closed')), ('closed', models.BooleanField(default=False, verbose_name='Closed')),
('car', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.car', verbose_name='Car')), ('car', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.car', verbose_name='Car')),
('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL)), ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.customer')),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.dealer')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.dealer')),
('estimate', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='opportunity', to=settings.DJANGO_LEDGER_ESTIMATE_MODEL)),
('lead', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunity', to='inventory.lead')),
('staff', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='owner', to='inventory.staff', verbose_name='Owner')), ('staff', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='owner', to='inventory.staff', verbose_name='Owner')),
], ],
options={ options={
@ -663,8 +602,8 @@ class Migration(migrations.Migration):
name='LeadStatusHistory', name='LeadStatusHistory',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('old_status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], max_length=50, verbose_name='Old Status')), ('old_status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('canceled', 'Canceled')], max_length=50, verbose_name='Old Status')),
('new_status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], max_length=50, verbose_name='New Status')), ('new_status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('canceled', 'Canceled')], max_length=50, verbose_name='New Status')),
('changed_at', models.DateTimeField(auto_now_add=True, verbose_name='Changed At')), ('changed_at', models.DateTimeField(auto_now_add=True, verbose_name='Changed At')),
('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='status_history', to='inventory.lead')), ('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='status_history', to='inventory.lead')),
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='status_changes', to='inventory.staff')), ('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='status_changes', to='inventory.staff')),
@ -679,6 +618,40 @@ class Migration(migrations.Migration):
name='staff', name='staff',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned', to='inventory.staff', verbose_name='Assigned'), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned', to='inventory.staff', verbose_name='Assigned'),
), ),
migrations.CreateModel(
name='Subscription',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('start_date', models.DateField(help_text='Date when the subscription starts')),
('end_date', models.DateField(help_text='Date when the subscription ends')),
('is_active', models.BooleanField(default=True)),
('billing_cycle', models.CharField(choices=[('monthly', 'Monthly'), ('annual', 'Annual')], default='monthly', help_text='Billing cycle for the subscription', max_length=10)),
('last_payment_date', models.DateField(blank=True, help_text='Date of the last payment made', null=True)),
('next_payment_date', models.DateField(blank=True, help_text='Date of the next payment due', null=True)),
('plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subscriptions', to='inventory.subscriptionplan')),
],
options={
'verbose_name': 'Subscription',
'verbose_name_plural': 'Subscriptions',
},
),
migrations.CreateModel(
name='SubscriptionUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subscription', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.subscription')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Subscription User',
'verbose_name_plural': 'Subscription Users',
},
),
migrations.AddField(
model_name='subscription',
name='users',
field=models.ManyToManyField(through='inventory.SubscriptionUser', to=settings.AUTH_USER_MODEL),
),
migrations.CreateModel( migrations.CreateModel(
name='UserActivityLog', name='UserActivityLog',
fields=[ fields=[
@ -731,23 +704,11 @@ class Migration(migrations.Migration):
'unique_together': {('car', 'reserved_until')}, 'unique_together': {('car', 'reserved_until')},
}, },
), ),
migrations.CreateModel(
name='DealersMake',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('added_at', models.DateTimeField(auto_now_add=True)),
('car_make', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='car_dealers', to='inventory.carmake')),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dealer_makes', to='inventory.dealer')),
],
options={
'unique_together': {('dealer', 'car_make')},
},
),
migrations.CreateModel( migrations.CreateModel(
name='CarColors', name='CarColors',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('car', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='colors', to='inventory.car')), ('car', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='colors', to='inventory.car')),
('exterior', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='colors', to='inventory.exteriorcolors')), ('exterior', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='colors', to='inventory.exteriorcolors')),
('interior', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='colors', to='inventory.interiorcolors')), ('interior', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='colors', to='inventory.interiorcolors')),
], ],

View File

@ -0,0 +1,19 @@
# Generated by Django 5.1.5 on 2025-02-04 04:37
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='carregistration',
name='car',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='registrations', to='inventory.car', verbose_name='Car'),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.17 on 2025-02-04 09:34
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL),
('inventory', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='lead',
name='customer',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='leads', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL),
),
]

View File

@ -0,0 +1,46 @@
# Generated by Django 4.2.17 on 2025-02-04 11:38
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import phonenumber_field.modelfields
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL),
('inventory', '0002_alter_lead_customer'),
]
operations = [
migrations.AddField(
model_name='lead',
name='email',
field=models.EmailField(default='x@tenhal.sa', max_length=254, verbose_name='Email'),
preserve_default=False,
),
migrations.AddField(
model_name='lead',
name='first_name',
field=models.CharField(default='test', max_length=50, verbose_name='First Name'),
preserve_default=False,
),
migrations.AddField(
model_name='lead',
name='last_name',
field=models.CharField(default='test', max_length=50, verbose_name='Last Name'),
preserve_default=False,
),
migrations.AddField(
model_name='lead',
name='phone_number',
field=phonenumber_field.modelfields.PhoneNumberField(default='056523656', max_length=128, region='SA', verbose_name='Phone Number'),
preserve_default=False,
),
migrations.AlterField(
model_name='lead',
name='customer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='leads', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.17 on 2025-02-04 14:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0003_lead_email_lead_first_name_lead_last_name_and_more'),
]
operations = [
migrations.RemoveField(
model_name='lead',
name='city',
),
migrations.AddField(
model_name='lead',
name='address',
field=models.CharField(default='', max_length=50, verbose_name='address'),
preserve_default=False,
),
]

View File

@ -0,0 +1,33 @@
# Generated by Django 4.2.17 on 2025-02-04 15:15
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL),
('inventory', '0004_remove_lead_city_lead_address'),
]
operations = [
migrations.CreateModel(
name='Schedule',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('purpose', models.CharField(max_length=200)),
('scheduled_at', models.DateTimeField()),
('notes', models.TextField(blank=True, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL)),
('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='inventory.lead')),
('scheduled_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.staff')),
],
options={
'ordering': ['-scheduled_at'],
},
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-04 15:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0005_schedule'),
]
operations = [
migrations.AlterField(
model_name='schedule',
name='purpose',
field=models.CharField(choices=[('Product Demo', 'Product Demo'), ('Follow-Up Call', 'Follow-Up Call'), ('Contract Discussion', 'Contract Discussion'), ('Sales Meeting', 'Sales Meeting'), ('Support Call', 'Support Call'), ('Other', 'Other')], max_length=200),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-04 15:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0006_alter_schedule_purpose'),
]
operations = [
migrations.AddField(
model_name='schedule',
name='scheduled_type',
field=models.CharField(choices=[('Call', 'Call'), ('Meeting', 'Meeting'), ('Email', 'Email')], default='Call', max_length=200),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-05 09:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0007_schedule_scheduled_type'),
]
operations = [
migrations.AddField(
model_name='schedule',
name='status',
field=models.CharField(choices=[('Scheduled', 'Scheduled'), ('Completed', 'Completed'), ('Canceled', 'Canceled')], default='Scheduled', max_length=200),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.17 on 2025-02-05 10:00
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL),
('inventory', '0008_schedule_status'),
]
operations = [
migrations.AlterField(
model_name='opportunity',
name='customer',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL),
),
]

View File

@ -0,0 +1,27 @@
# Generated by Django 4.2.17 on 2025-02-05 10:05
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0009_alter_opportunity_customer'),
]
operations = [
migrations.RemoveField(
model_name='lead',
name='id_car_make',
),
migrations.RemoveField(
model_name='lead',
name='id_car_model',
),
migrations.AddField(
model_name='lead',
name='car',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.car', verbose_name='Car'),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.2.17 on 2025-02-05 10:17
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL),
('inventory', '0010_remove_lead_id_car_make_remove_lead_id_car_model_and_more'),
]
operations = [
migrations.RemoveField(
model_name='lead',
name='year',
),
migrations.AlterField(
model_name='schedule',
name='customer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL),
),
]

View File

@ -0,0 +1,14 @@
# Generated by Django 5.1.5 on 2025-02-06 08:51
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '0002_alter_carregistration_car'),
('inventory', '0011_remove_lead_year_alter_schedule_customer'),
]
operations = [
]

View File

@ -0,0 +1,14 @@
# Generated by Django 4.2.17 on 2025-02-06 10:08
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '0002_alter_carregistration_car'),
('inventory', '0011_remove_lead_year_alter_schedule_customer'),
]
operations = [
]

View File

@ -0,0 +1,23 @@
# Generated by Django 5.1.5 on 2025-02-07 01:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0012_merge_20250206_1151'),
]
operations = [
migrations.AlterField(
model_name='carregistration',
name='text2',
field=models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 2'),
),
migrations.AlterField(
model_name='carregistration',
name='text3',
field=models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 3'),
),
]

View File

@ -0,0 +1,33 @@
# Generated by Django 4.2.17 on 2025-02-06 12:07
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0013_alter_carregistration_text2_and_more'),
]
operations = [
migrations.RemoveField(
model_name='lead',
name='car',
),
migrations.AddField(
model_name='lead',
name='id_car_make',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make'),
),
migrations.AddField(
model_name='lead',
name='id_car_model',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel', verbose_name='Model'),
),
migrations.AddField(
model_name='lead',
name='year',
field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Year'),
),
]

View File

@ -0,0 +1,14 @@
# Generated by Django 4.2.17 on 2025-02-09 08:16
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '0012_merge_20250206_1308'),
('inventory', '0014_remove_lead_car_lead_id_car_make_lead_id_car_model_and_more'),
]
operations = [
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.2.17 on 2025-02-09 08:23
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0015_merge_20250209_1116'),
]
operations = [
migrations.AddField(
model_name='schedule',
name='duration',
field=models.DurationField(default=datetime.timedelta(seconds=300)),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-09 11:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0016_schedule_duration'),
]
operations = [
migrations.AddField(
model_name='car',
name='hash',
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='Hash'),
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 5.1.5 on 2025-02-11 00:23
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0017_car_hash'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='customer',
name='user',
field=models.OneToOneField(default=4, on_delete=django.db.models.deletion.CASCADE, related_name='customer_profile', to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.2.17 on 2025-02-12 10:26
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0018_customer_user'),
]
operations = [
migrations.AddField(
model_name='opportunity',
name='lead',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='inventory.lead'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-12 10:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0019_opportunity_lead'),
]
operations = [
migrations.AlterField(
model_name='opportunity',
name='closing_date',
field=models.DateField(blank=True, null=True, verbose_name='Closing Date'),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.2.17 on 2025-02-12 10:37
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0020_alter_opportunity_closing_date'),
]
operations = [
migrations.AlterField(
model_name='opportunity',
name='lead',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunity', to='inventory.lead'),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.17 on 2025-02-12 14:09
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_ESTIMATE_MODEL),
('inventory', '0021_alter_opportunity_lead'),
]
operations = [
migrations.AddField(
model_name='opportunity',
name='estimate',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='opportunity', to=settings.DJANGO_LEDGER_ESTIMATE_MODEL),
),
]

View File

@ -0,0 +1,36 @@
# Generated by Django 4.2.17 on 2025-02-13 09:01
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
('inventory', '0022_opportunity_estimate'),
]
operations = [
migrations.CreateModel(
name='Email',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.PositiveIntegerField()),
('from_email', models.TextField(blank=True, null=True, verbose_name='From Email')),
('to_email', models.TextField(blank=True, null=True, verbose_name='To Email')),
('subject', models.TextField(blank=True, null=True, verbose_name='Subject')),
('body', models.TextField(blank=True, null=True, verbose_name='Body')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='emails_created', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Email',
'verbose_name_plural': 'Emails',
},
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 4.2.17 on 2025-02-13 09:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0023_email'),
]
operations = [
migrations.RemoveField(
model_name='email',
name='body',
),
migrations.AddField(
model_name='email',
name='message',
field=models.TextField(blank=True, null=True, verbose_name='Message'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-13 09:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0024_remove_email_body_email_message'),
]
operations = [
migrations.AddField(
model_name='email',
name='status',
field=models.CharField(choices=[('SENT', 'Sent'), ('FAILED', 'Failed'), ('DELIVERED', 'Delivered'), ('OPEN', 'Open'), ('DRAFT', 'Draft')], default='OPEN', max_length=20, verbose_name='Status'),
),
]

View File

@ -0,0 +1,29 @@
# Generated by Django 4.2.17 on 2025-02-17 08:54
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0025_email_status'),
]
operations = [
migrations.CreateModel(
name='CarHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('event_date', models.DateField()),
('event_type', models.CharField(choices=[('PURCHASE', 'Purchase'), ('SALE', 'Sale'), ('TRANSFER', 'Transfer'), ('ACCIDENT', 'Accident'), ('MAINTENANCE', 'Maintenance'), ('SERVICE', 'Service'), ('OTHER', 'Other')], max_length=50)),
('description', models.TextField(blank=True, null=True)),
('mileage', models.IntegerField(blank=True, null=True)),
('cost', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
('car', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='history', to='inventory.car')),
],
options={
'ordering': ['-event_date'],
},
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 4.2.17 on 2025-02-17 08:57
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0026_carhistory'),
]
operations = [
migrations.AddField(
model_name='carhistory',
name='dealer',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='history', to='inventory.dealer'),
preserve_default=False,
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-17 09:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0027_carhistory_dealer'),
]
operations = [
migrations.AddField(
model_name='carhistory',
name='additional_info',
field=models.JSONField(blank=True, default=dict, null=True, verbose_name='Car History Additional Info'),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.17 on 2025-02-17 09:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '0028_carhistory_additional_info'),
]
operations = [
migrations.RemoveField(
model_name='carhistory',
name='cost',
),
migrations.RemoveField(
model_name='carhistory',
name='mileage',
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.17 on 2025-02-17 09:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0029_remove_carhistory_cost_remove_carhistory_mileage'),
]
operations = [
migrations.AlterField(
model_name='activity',
name='activity_type',
field=models.CharField(choices=[('call', 'Call'), ('sms', 'SMS'), ('email', 'Email'), ('whatsapp', 'WhatsApp'), ('visit', 'Visit'), ('add_car', 'Add Car'), ('sale_car', 'Sale Car'), ('reserve_car', 'Reserve Car'), ('transfer_car', 'Transfer Car'), ('remove_car', 'Remove Car'), ('create_quotation', 'Create Quotation'), ('cancel_quotation', 'Cancel Quotation'), ('create_order', 'Create Order'), ('cancel_order', 'Cancel Order'), ('create_invoice', 'Create Invoice'), ('cancel_invoice', 'Cancel Invoice')], max_length=50, verbose_name='Activity Type'),
),
migrations.DeleteModel(
name='CarHistory',
),
]

View File

@ -0,0 +1,33 @@
# Generated by Django 5.1.5 on 2025-02-17 14:05
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('inventory', '0030_alter_activity_activity_type_delete_carhistory'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='activity',
name='dealer',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='inventory.dealer'),
preserve_default=False,
),
migrations.AlterField(
model_name='activity',
name='content_type',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='contenttypes.contenttype'),
),
migrations.AlterField(
model_name='activity',
name='created_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='activities_created_by', to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 5.1.6 on 2025-02-17 17:40
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0031_activity_dealer_alter_activity_content_type_and_more'),
]
operations = [
migrations.AlterField(
model_name='carcolors',
name='car',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='colors', to='inventory.car'),
),
]

View File

@ -0,0 +1,32 @@
# Generated by Django 5.1.6 on 2025-02-19 05:25
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
# ('appointment', '0002_alter_workinghours_options'),
('inventory', '0032_alter_carcolors_car'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RemoveField(
model_name='staff',
name='user',
),
migrations.AddField(
model_name='staff',
name='staff_member',
field=models.OneToOneField(default=5, on_delete=django.db.models.deletion.CASCADE, related_name='staff', to='appointment.staffmember'),
preserve_default=False,
),
migrations.AlterField(
model_name='schedule',
name='scheduled_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,38 @@
# Generated by Django 5.1.6 on 2025-02-20 01:29
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '0033_remove_staff_user_staff_staff_member_and_more'),
]
operations = [
migrations.RemoveField(
model_name='subscription',
name='plan',
),
migrations.RemoveField(
model_name='subscription',
name='users',
),
migrations.RemoveField(
model_name='subscriptionuser',
name='subscription',
),
migrations.RemoveField(
model_name='subscriptionuser',
name='user',
),
migrations.DeleteModel(
name='SubscriptionPlan',
),
migrations.DeleteModel(
name='Subscription',
),
migrations.DeleteModel(
name='SubscriptionUser',
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.2.17 on 2025-02-20 08:16
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
# ('inventory', '0037_alter_schedule_scheduled_type'),
('inventory', '0034_remove_subscription_plan_remove_subscription_users_and_more'),
]
operations = [
migrations.CreateModel(
name='CustomGroup',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.dealer')),
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.group', verbose_name='')),
],
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.2.17 on 2025-02-20 08:17
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0038_customgroup'),
]
operations = [
migrations.AlterField(
model_name='customgroup',
name='dealer',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='groups', to='inventory.dealer'),
),
]

View File

@ -0,0 +1,33 @@
# Generated by Django 4.2.17 on 2025-02-23 14:31
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_ACCOUNT_MODEL),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('inventory', '0039_alter_customgroup_dealer'),
]
operations = [
migrations.CreateModel(
name='UserSettings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('language', models.CharField(choices=[('en', 'English'), ('ar', 'Arabic')], default='ar', max_length=20)),
('theme', models.CharField(choices=[('default', 'Default'), ('dark', 'Dark')], default='default', max_length=20)),
('additional_info', models.JSONField(default=dict)),
('bill_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_ca', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('bill_payable_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_payable', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('bill_prepaid_expense_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_prepaid_expense', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('invoice_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_ca', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('invoice_payable_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_payable', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('invoice_prepaid_expense_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_prepaid_expense', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-23 14:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0040_usersettings'),
]
operations = [
migrations.AlterField(
model_name='usersettings',
name='additional_info',
field=models.JSONField(blank=True, default=dict, null=True),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.17 on 2025-02-23 15:34
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('inventory', '0041_alter_usersettings_additional_info'),
]
operations = [
migrations.AlterField(
model_name='usersettings',
name='user',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='settings', to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2.17 on 2025-02-23 16:23
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('inventory', '0042_alter_usersettings_user'),
]
operations = [
migrations.AlterField(
model_name='usersettings',
name='user',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='settings', to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,33 @@
# Generated by Django 4.2.17 on 2025-02-23 16:31
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_ACCOUNT_MODEL),
('inventory', '0043_alter_usersettings_user'),
]
operations = [
migrations.CreateModel(
name='DealerSettings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('additional_info', models.JSONField(blank=True, default=dict, null=True)),
('bill_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_ca', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('bill_payable_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_payable', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('bill_prepaid_expense_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_prepaid_expense', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('dealer', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='settings', to='inventory.dealer')),
('invoice_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_ca', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('invoice_payable_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_payable', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
('invoice_prepaid_expense_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_prepaid_expense', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)),
],
),
migrations.DeleteModel(
name='UserSettings',
),
]

View File

@ -0,0 +1,39 @@
# Generated by Django 4.2.17 on 2025-02-24 09:01
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_ACCOUNT_MODEL),
('inventory', '0044_dealersettings_delete_usersettings'),
]
operations = [
migrations.RemoveField(
model_name='dealersettings',
name='invoice_payable_account',
),
migrations.RemoveField(
model_name='dealersettings',
name='invoice_prepaid_expense_account',
),
migrations.AddField(
model_name='dealersettings',
name='invoice_prepaid_account',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL),
),
migrations.AddField(
model_name='dealersettings',
name='invoice_unearned_account',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_unearned', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL),
),
migrations.AlterField(
model_name='dealersettings',
name='invoice_cash_account',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_cash', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.2.17 on 2025-02-24 09:10
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_ACCOUNT_MODEL),
('inventory', '0045_remove_dealersettings_invoice_payable_account_and_more'),
]
operations = [
migrations.RemoveField(
model_name='dealersettings',
name='invoice_prepaid_account',
),
migrations.AddField(
model_name='dealersettings',
name='invoice_recivable_account',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_recivable', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.2.17 on 2025-02-24 09:11
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_ACCOUNT_MODEL),
('inventory', '0046_remove_dealersettings_invoice_prepaid_account_and_more'),
]
operations = [
migrations.RemoveField(
model_name='dealersettings',
name='invoice_recivable_account',
),
migrations.AddField(
model_name='dealersettings',
name='invoice_prepaid_account',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL),
),
]

View File

@ -0,0 +1,39 @@
# Generated by Django 4.2.17 on 2025-02-24 09:14
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.DJANGO_LEDGER_ACCOUNT_MODEL),
('inventory', '0047_remove_dealersettings_invoice_recivable_account_and_more'),
]
operations = [
migrations.RemoveField(
model_name='dealersettings',
name='bill_payable_account',
),
migrations.RemoveField(
model_name='dealersettings',
name='bill_prepaid_expense_account',
),
migrations.AddField(
model_name='dealersettings',
name='bill_prepaid_account',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL),
),
migrations.AddField(
model_name='dealersettings',
name='bill_unearned_account',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_unearned', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL),
),
migrations.AlterField(
model_name='dealersettings',
name='bill_cash_account',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_cash', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL),
),
]

View File

@ -0,0 +1,33 @@
# Generated by Django 4.2.17 on 2025-02-26 08:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0048_remove_dealersettings_bill_payable_account_and_more'),
]
operations = [
migrations.AlterField(
model_name='lead',
name='status',
field=models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], db_index=True, default='new', max_length=50, verbose_name='Status'),
),
migrations.AlterField(
model_name='leadstatushistory',
name='new_status',
field=models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], max_length=50, verbose_name='New Status'),
),
migrations.AlterField(
model_name='leadstatushistory',
name='old_status',
field=models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], max_length=50, verbose_name='Old Status'),
),
migrations.AlterField(
model_name='opportunity',
name='status',
field=models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], default='new', max_length=20, verbose_name='Status'),
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 5.1.6 on 2025-02-24 17:25
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0048_remove_dealersettings_bill_payable_account_and_more'),
migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL),
]
operations = [
migrations.AddField(
model_name='carreservation',
name='reserved_for',
field=models.ForeignKey(default='dd747dc3-39bc-411f-a17d-c930a50220fe', on_delete=django.db.models.deletion.CASCADE, related_name='reservations', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL, verbose_name='Reserved For'),
preserve_default=False,
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 5.1.6 on 2025-02-25 01:05
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '0049_carreservation_reserved_for'),
]
operations = [
migrations.RemoveField(
model_name='carreservation',
name='reserved_for',
),
]

View File

@ -0,0 +1,14 @@
# Generated by Django 4.2.17 on 2025-02-26 13:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '0049_alter_lead_status_alter_leadstatushistory_new_status_and_more'),
('inventory', '0050_remove_carreservation_reserved_for'),
]
operations = [
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-02-27 15:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0051_merge_20250226_1654'),
]
operations = [
migrations.AddField(
model_name='lead',
name='lead_type',
field=models.CharField(choices=[('customer', 'Customer'), ('organization', 'Organization')], default='customer', max_length=50, verbose_name='Lead Type'),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.17 on 2025-03-01 21:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0052_lead_lead_type'),
]
operations = [
migrations.AddField(
model_name='lead',
name='crn',
field=models.CharField(blank=True, max_length=10, null=True, unique=True, verbose_name='Commercial Registration Number'),
),
migrations.AddField(
model_name='lead',
name='vrn',
field=models.CharField(blank=True, max_length=15, null=True, unique=True, verbose_name='VAT Registration Number'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-03-04 01:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0053_lead_crn_lead_vrn'),
]
operations = [
migrations.AlterField(
model_name='staff',
name='staff_type',
field=models.CharField(choices=[('inventory', 'Inventory'), ('accountant', 'Accountant'), ('sales', 'Sales')], max_length=255, verbose_name='Staff Type'),
),
]

View File

@ -0,0 +1,26 @@
# Generated by Django 5.1.6 on 2025-03-03 16:59
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0053_lead_crn_lead_vrn'),
]
operations = [
migrations.CreateModel(
name='DealersMake',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('added_at', models.DateTimeField(auto_now_add=True)),
('car_make', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='car_dealers', to='inventory.carmake')),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dealer_makes', to='inventory.dealer')),
],
options={
'unique_together': {('dealer', 'car_make')},
},
),
]

View File

@ -0,0 +1,14 @@
# Generated by Django 4.2.17 on 2025-03-04 21:15
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '0054_alter_staff_staff_type'),
('inventory', '0054_dealersmake'),
]
operations = [
]

View File

@ -1,246 +1,265 @@
aiohappyeyeballs aiohappyeyeballs==2.4.6
aiohttp aiohttp==3.11.12
aiohttp-retry aiohttp-retry==2.9.1
aiosignal aiosignal==1.3.2
alabaster alabaster==1.0.0
albucore albucore==0.0.23
albumentations albumentations==2.0.4
annotated-types annotated-types==0.7.0
anyio anyio==4.8.0
arabic-reshaper arabic-reshaper==3.0.0
asgiref asgiref==3.8.1
astor astor==0.8.1
astroid astroid==3.3.8
attrs attrs==25.1.0
autopep8 autopep8==2.3.2
Babel Babel==2.15.0
beautifulsoup4 beautifulsoup4==4.13.3
bleach bleach==6.2.0
blinker blinker==1.9.0
Brotli Brotli==1.1.0
cattrs cattrs==24.1.2
certifi certifi==2025.1.31
cffi cffi==1.17.1
chardet chardet==5.2.0
charset-normalizer charset-normalizer==3.4.1
click click==8.1.8
colorama colorama==0.4.6
commonmark commonmark==0.9.1
contourpy contourpy==1.3.1
crispy-bootstrap5 crispy-bootstrap5==2024.10
cryptography cryptography==44.0.1
cssselect2 cssselect2==0.7.0
ctranslate2 ctranslate2==4.5.0
cycler cycler==0.12.1
Cython Cython==3.1.0a1
decorator decorator==5.1.1
defusedxml defusedxml==0.7.1
desert desert==2020.11.18
diff-match-patch diff-match-patch==20241021
dill dill==0.3.9
distro distro==1.9.0
dj-rest-auth dj-rest-auth==7.0.1
dj-shop-cart dj-shop-cart==8.0.0a2
Django Django==5.1.6
django-allauth django-allauth==65.4.1
django-appointment django-appointment==3.8.0
django-autoslug django-autoslug==1.9.9
django-bootstrap5 django-bootstrap5==24.3
django-classy-tags django-classy-tags==4.1.0
django-cors-headers django-cors-headers==4.7.0
django-countries django-countries==7.6.1
django-crispy-forms django-crispy-forms==2.3
django-debug-toolbar django-debug-toolbar==5.0.1
django-extensions django-extensions==3.2.3
django-filter django-filter==25.1
django-formtools django-formtools==2.5.1
django-import-export django-import-export==4.3.5
django-ledger django-ledger==0.7.4.1
django-model-utils django-model-utils==5.0.0
django-money django-money==3.5.3
django-next-url-mixin django-next-url-mixin==0.4.0
django-nine django-nine==0.2.7
django-nonefield django-nonefield==0.4
django-ordered-model django-ordered-model==3.7.4
django-pdf-actions django-pdf-actions==0.1.39
django-phonenumber-field django-phonenumber-field==8.0.0
django-picklefield django-picklefield==3.2
django-plans django-plans==1.2.0
django-prometheus django-prometheus==2.3.1
django-q2 django-q2==1.7.6
django-schema-graph django-schema-graph==3.1.0
django-sekizai django-sekizai==4.1.0
django-sequences django-sequences==3.0
django-silk django-silk==5.3.2
django-sms django-sms==0.7.0
django-sslserver django-sslserver==0.22
django-tables2 django-tables2==2.7.5
django-treebeard django-treebeard==4.7.1
django-view-breadcrumbs django-view-breadcrumbs==2.5.1
djangocms-admin-style djangocms-admin-style==3.3.1
djangorestframework djangorestframework==3.15.2
djangorestframework_simplejwt djangorestframework_simplejwt==5.4.0
djangoviz djangoviz==0.1.1
docopt docopt==0.6.2
docutils docutils==0.21.2
easy-thumbnails easy-thumbnails==2.10
emoji emoji==2.14.1
et_xmlfile et_xmlfile==2.0.0
Faker Faker==36.1.1
filelock filelock==3.17.0
fire fire==0.7.0
fonttools Flask==3.1.0
fpdf2 fonttools==4.56.0
frozenlist fpdf2==2.8.2
fsspec frozenlist==1.5.0
gprof2dot fsspec==2025.2.0
graphqlclient gprof2dot==2024.6.6
greenlet graphqlclient==0.2.4
h11 greenlet==3.1.1
h2 h11==0.14.0
hpack h2==4.2.0
hstspreload hpack==4.1.0
httpcore hstspreload==2025.1.1
httpx httpcore==1.0.7
hyperframe httpx==0.28.1
icalendar hyperframe==6.1.0
idna icalendar==6.1.1
imageio idna==3.10
imagesize imageio==2.37.0
imgaug imagesize==1.4.1
iso4217 imgaug==0.4.0
isodate iso4217==1.12.20240625
isort isodate==0.7.2
itsdangerous isort==6.0.0
Jinja2 itsdangerous==2.2.0
jiter Jinja2==3.1.5
joblib jiter==0.8.2
kiwisolver joblib==1.4.2
lazy_loader kiwisolver==1.4.8
ledger lazy_loader==0.4
libretranslatepy ledger==1.0.1
lmdb libretranslatepy==2.1.4
lxml lmdb==1.6.2
Markdown lxml==5.3.1
markdown-it-py Markdown==3.7
MarkupSafe markdown-it-py==3.0.0
marshmallow MarkupSafe==3.0.2
matplotlib marshmallow==3.26.1
mccabe matplotlib==3.10.0
mdurl mccabe==0.7.0
MouseInfo mdurl==0.1.2
mpmath MouseInfo==0.1.3
multidict mpmath==1.3.0
mypy-extensions multidict==6.1.0
networkx mypy-extensions==1.0.0
newrelic networkx==3.4.2
nltk newrelic==10.6.0
num2words nltk==3.9.1
numpy num2words==0.5.14
oauthlib numpy==2.2.3
ofxtools oauthlib==3.2.2
openai ofxtools==0.9.5
opencv-contrib-python openai==1.63.1
opencv-python opencv-contrib-python==4.11.0.86
opencv-python-headless opencv-python==4.11.0.86
openpyxl opencv-python-headless==4.11.0.86
opt_einsum openpyxl==3.1.5
outcome opt_einsum==3.4.0
packaging outcome==1.3.0.post0
pandas packaging==24.2
pango pandas==2.2.3
pdfkit pango==0.0.1
platformdirs pdfkit==1.0.0
prometheus_client phonenumbers==8.13.55
propcache pillow==11.1.0
protobuf platformdirs==4.3.6
psycopg-binary prometheus_client==0.21.1
py-moneyed propcache==0.2.1
PyAutoGUI protobuf==5.29.3
pyclipper psycopg==3.2.4
pycodestyle psycopg-binary==3.2.4
pycparser psycopg-c==3.2.4
pydotplus py-moneyed==3.0
pydyf PyAutoGUI==0.9.54
PyGetWindow pyclipper==1.3.0.post6
Pygments pycodestyle==2.12.1
PyJWT pycparser==2.22
pylint pydantic==2.10.6
PyMsgBox pydantic_core==2.29.0
pyparsing pydotplus==2.0.2
pypdf pydyf==0.11.0
PyPDF2 PyGetWindow==0.0.9
pyperclip Pygments==2.19.1
pyphen PyJWT==2.10.1
pypng pylint==3.3.4
PyRect PyMsgBox==1.0.9
PyScreeze PyMySQL==1.1.1
pyserial pyobjc-core==11.0
PySocks pyobjc-framework-Cocoa==11.0
python-bidi pyobjc-framework-Quartz==11.0
python-dateutil pyparsing==3.2.1
python-docx pypdf==5.3.0
python-openid PyPDF2==3.0.1
python-stdnum pyperclip==1.9.0
python3-saml pyphen==0.17.2
pytweening pypng==0.20220715.0
pytz PyRect==0.2.0
pyvin PyScreeze==1.0.1
pyzbar pyserial==3.5
qrcode PySocks==1.7.1
RapidFuzz python-bidi==0.6.3
regex python-dateutil==2.9.0.post0
reportlab python-docx==1.1.2
requests python-openid==2.2.5
requests-oauthlib python-stdnum==1.20
rfc3986 python3-saml==1.16.0
rich pytweening==1.2.0
rubicon-objc pytz==2025.1
sacremoses pyvin==0.0.2
scikit-image pywa==2.7.0
scikit-learn pywhat==5.1.0
scipy pywhatkit==5.4
selenium PyYAML==6.0.2
sentencepiece pyzbar==0.1.9
shapely qrcode==8.0
simsimd RapidFuzz==3.12.1
six regex==2024.11.6
sniffio reportlab==4.3.1
snowballstemmer requests==2.32.3
sortedcontainers requests-oauthlib==2.0.0
soupsieve rfc3986==2.0.0
sqlparse rich==13.9.4
stanza rubicon-objc==0.5.0
stringzilla sacremoses==0.1.1
suds scikit-image==0.25.1
sympy scikit-learn==1.6.1
tablib scipy==1.15.2
termcolor selenium==4.28.1
threadpoolctl sentencepiece==0.2.0
tifffile shapely==2.0.7
tomli simsimd==6.2.1
tomlkit six==1.17.0
tqdm sniffio==1.3.1
trio snowballstemmer==2.2.0
trio-websocket sortedcontainers==2.4.0
typing-inspect soupsieve==2.6
typing_extensions SQLAlchemy==2.0.38
tzdata sqlparse==0.5.3
Unidecode stanza==1.10.1
upgrade-requirements stringzilla==3.11.3
urllib3 suds==1.2.0
vishap swapper==1.4.0
vpic-api sympy==1.13.1
weasyprint tablib==3.8.0
webencodings termcolor==2.5.0
websocket-client threadpoolctl==3.5.0
Werkzeug tifffile==2025.1.10
wikipedia tinycss2==1.4.0
wsproto tinyhtml5==2.0.0
yarl tomli==2.2.1
zopfli tomlkit==0.13.2
python-dotenv torch==2.6.0
psycopg2-binary tqdm==4.67.1
phonenumbers trio==0.29.0
swapper trio-websocket==0.12.0
pillow twilio==9.4.5
typing-inspect==0.9.0
typing_extensions==4.12.2
tzdata==2025.1
Unidecode==1.3.8
upgrade-requirements==1.7.0
urllib3==2.3.0
vin==0.6.2
vininfo==1.8.0
vishap==0.1.5
vpic-api==0.7.4
weasyprint==64.0
webencodings==0.5.1
websocket-client==1.8.0
Werkzeug==3.1.3
wikipedia==1.4.0
wsproto==1.2.0
xmlsec==1.3.14
yarl==1.18.3
zopfli==0.2.3.post1

View File

@ -1,5 +1,3 @@
import os
from dotenv import load_dotenv
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django_ledger.models.invoice import InvoiceModel from django_ledger.models.invoice import InvoiceModel
@ -19,7 +17,6 @@ import hashlib
User = get_user_model() User = get_user_model()
load_dotenv(".env")
def run(): def run():
# print(Service.objects.first().pk) # print(Service.objects.first().pk)
# print(Appointment.objects.first().client) # print(Appointment.objects.first().client)
@ -148,8 +145,7 @@ def run():
# print(Permission.objects.filter(codename__in=['view_car','view_carlocation','view_customcard','view_carcolors','view_cartransfer','view_estimatemodel','view_invoicemodel','view_saleorder'])) # print(Permission.objects.filter(codename__in=['view_car','view_carlocation','view_customcard','view_carcolors','view_cartransfer','view_estimatemodel','view_invoicemodel','view_saleorder']))
# print(Permission.objects.filter(codename__in=['view_estimatemodel','view_invoicemodel','view_saleorder'])) # print(Permission.objects.filter(codename__in=['view_estimatemodel','view_invoicemodel','view_saleorder']))
# CustomGroup.objects.filter(name='Accountant').last().set_default_permissions() # CustomGroup.objects.filter(name='Accountant').last().set_default_permissions()
# CustomGroup.objects.filter(name='Inventory').last().set_default_permissions() CustomGroup.objects.filter(name='Inventory').last().set_default_permissions()
# EntityManagementModel.objects.create(entity=,user=) # EntityManagementModel.objects.create(entity=,user=)
# print(Permission.objects.filter(codename__icontains='customermodel').first().codename) # print(Permission.objects.filter(codename__icontains='customermodel').first().codename)
print(os.getenv("DJANGO_ALLOWED_HOSTS"))

View File

@ -273,15 +273,3 @@ select.admin-autocomplete {
display: block; display: block;
padding: 6px; padding: 6px;
} }
.errors .select2-selection {
border: 1px solid var(--error-fg);
}
.errors .select2-selection {
border: 1px solid var(--error-fg);
}
.errors .select2-selection {
border: 1px solid var(--error-fg);
}

View File

@ -13,7 +13,6 @@ html[data-theme="light"],
--body-fg: #333; --body-fg: #333;
--body-bg: #fff; --body-bg: #fff;
--body-quiet-color: #666; --body-quiet-color: #666;
--body-medium-color: #444;
--body-loud-color: #000; --body-loud-color: #000;
--header-color: #ffc; --header-color: #ffc;
@ -23,11 +22,11 @@ html[data-theme="light"],
--breadcrumbs-fg: #c4dce8; --breadcrumbs-fg: #c4dce8;
--breadcrumbs-link-fg: var(--body-bg); --breadcrumbs-link-fg: var(--body-bg);
--breadcrumbs-bg: #264b5d; --breadcrumbs-bg: var(--primary);
--link-fg: #417893; --link-fg: #417893;
--link-hover-color: #036; --link-hover-color: #036;
--link-selected-fg: var(--secondary); --link-selected-fg: #5b80b2;
--hairline-color: #e8e8e8; --hairline-color: #e8e8e8;
--border-color: #ccc; --border-color: #ccc;
@ -43,10 +42,10 @@ html[data-theme="light"],
--selected-row: #ffc; --selected-row: #ffc;
--button-fg: #fff; --button-fg: #fff;
--button-bg: var(--secondary); --button-bg: var(--primary);
--button-hover-bg: #205067; --button-hover-bg: #609ab6;
--default-button-bg: #205067; --default-button-bg: var(--secondary);
--default-button-hover-bg: var(--secondary); --default-button-hover-bg: #205067;
--close-button-bg: #747474; --close-button-bg: #747474;
--close-button-hover-bg: #333; --close-button-hover-bg: #333;
--delete-button-bg: #ba2121; --delete-button-bg: #ba2121;
@ -57,6 +56,8 @@ html[data-theme="light"],
--object-tools-hover-bg: var(--close-button-hover-bg); --object-tools-hover-bg: var(--close-button-hover-bg);
--font-family-primary: --font-family-primary:
-apple-system,
BlinkMacSystemFont,
"Segoe UI", "Segoe UI",
system-ui, system-ui,
Roboto, Roboto,
@ -85,8 +86,6 @@ html[data-theme="light"],
"Segoe UI Emoji", "Segoe UI Emoji",
"Segoe UI Symbol", "Segoe UI Symbol",
"Noto Color Emoji"; "Noto Color Emoji";
color-scheme: light;
} }
html, body { html, body {
@ -150,6 +149,7 @@ h1 {
margin: 0 0 20px; margin: 0 0 20px;
font-weight: 300; font-weight: 300;
font-size: 1.25rem; font-size: 1.25rem;
color: var(--body-quiet-color);
} }
h2 { h2 {
@ -165,7 +165,7 @@ h2.subhead {
h3 { h3 {
font-size: 0.875rem; font-size: 0.875rem;
margin: .8em 0 .3em 0; margin: .8em 0 .3em 0;
color: var(--body-medium-color); color: var(--body-quiet-color);
font-weight: bold; font-weight: bold;
} }
@ -173,7 +173,6 @@ h4 {
font-size: 0.75rem; font-size: 0.75rem;
margin: 1em 0 .8em 0; margin: 1em 0 .8em 0;
padding-bottom: 3px; padding-bottom: 3px;
color: var(--body-medium-color);
} }
h5 { h5 {
@ -220,10 +219,6 @@ fieldset {
border-top: 1px solid var(--hairline-color); border-top: 1px solid var(--hairline-color);
} }
details summary {
cursor: pointer;
}
blockquote { blockquote {
font-size: 0.6875rem; font-size: 0.6875rem;
color: #777; color: #777;
@ -320,7 +315,7 @@ td, th {
} }
th { th {
font-weight: 500; font-weight: 600;
text-align: left; text-align: left;
} }
@ -341,7 +336,7 @@ tfoot td {
} }
thead th.required { thead th.required {
font-weight: bold; color: var(--body-loud-color);
} }
tr.alt { tr.alt {
@ -489,13 +484,8 @@ textarea {
vertical-align: top; vertical-align: top;
} }
/* input[type=text], input[type=password], input[type=email], input[type=url],
Minifiers remove the default (text) "type" attribute from "input" HTML tags. input[type=number], input[type=tel], textarea, select, .vTextField {
Add input:not([type]) to make the CSS stylesheet work the same.
*/
input:not([type]), input[type=text], input[type=password], input[type=email],
input[type=url], input[type=number], input[type=tel], textarea, select,
.vTextField {
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
border-radius: 4px; border-radius: 4px;
padding: 5px 6px; padding: 5px 6px;
@ -504,13 +494,9 @@ input[type=url], input[type=number], input[type=tel], textarea, select,
background-color: var(--body-bg); background-color: var(--body-bg);
} }
/* input[type=text]:focus, input[type=password]:focus, input[type=email]:focus,
Minifiers remove the default (text) "type" attribute from "input" HTML tags. input[type=url]:focus, input[type=number]:focus, input[type=tel]:focus,
Add input:not([type]) to make the CSS stylesheet work the same. textarea:focus, select:focus, .vTextField:focus {
*/
input:not([type]):focus, input[type=text]:focus, input[type=password]:focus,
input[type=email]:focus, input[type=url]:focus, input[type=number]:focus,
input[type=tel]:focus, textarea:focus, select:focus, .vTextField:focus {
border-color: var(--body-quiet-color); border-color: var(--body-quiet-color);
} }
@ -600,7 +586,7 @@ input[type=button][disabled].default {
font-weight: 400; font-weight: 400;
font-size: 0.8125rem; font-size: 0.8125rem;
text-align: left; text-align: left;
background: var(--header-bg); background: var(--primary);
color: var(--header-link-color); color: var(--header-link-color);
} }
@ -736,11 +722,6 @@ div.breadcrumbs a:focus, div.breadcrumbs a:hover {
background: url(../img/icon-viewlink.svg) 0 1px no-repeat; background: url(../img/icon-viewlink.svg) 0 1px no-repeat;
} }
.hidelink {
padding-left: 16px;
background: url(../img/icon-hidelink.svg) 0 1px no-repeat;
}
.addlink { .addlink {
padding-left: 16px; padding-left: 16px;
background: url(../img/icon-addlink.svg) 0 1px no-repeat; background: url(../img/icon-addlink.svg) 0 1px no-repeat;
@ -850,6 +831,10 @@ a.deletelink:focus, a.deletelink:hover {
height: 100%; height: 100%;
} }
#container > div {
flex-shrink: 0;
}
#container > .main { #container > .main {
display: flex; display: flex;
flex: 1 0 auto; flex: 1 0 auto;
@ -894,10 +879,9 @@ a.deletelink:focus, a.deletelink:hover {
margin-right: -300px; margin-right: -300px;
} }
@media (forced-colors: active) { #footer {
#content-related { clear: both;
border: 1px solid; padding: 10px;
}
} }
/* COLUMN TYPES */ /* COLUMN TYPES */
@ -935,6 +919,7 @@ a.deletelink:focus, a.deletelink:hover {
padding: 10px 40px; padding: 10px 40px;
background: var(--header-bg); background: var(--header-bg);
color: var(--header-color); color: var(--header-color);
overflow: hidden;
} }
#header a:link, #header a:visited, #logout-form button { #header a:link, #header a:visited, #logout-form button {
@ -945,17 +930,11 @@ a.deletelink:focus, a.deletelink:hover {
text-decoration: underline; text-decoration: underline;
} }
@media (forced-colors: active) {
#header {
border-bottom: 1px solid;
}
}
#branding { #branding {
display: flex; display: flex;
} }
#site-name { #branding h1 {
padding: 0; padding: 0;
margin: 0; margin: 0;
margin-inline-end: 20px; margin-inline-end: 20px;
@ -964,7 +943,7 @@ a.deletelink:focus, a.deletelink:hover {
color: var(--header-branding-color); color: var(--header-branding-color);
} }
#site-name a:link, #site-name a:visited { #branding h1 a:link, #branding h1 a:visited {
color: var(--accent); color: var(--accent);
} }
@ -1164,16 +1143,3 @@ a.deletelink:focus, a.deletelink:hover {
.base-svgs { .base-svgs {
display: none; display: none;
} }
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
border: 0;
color: var(--body-fg);
background-color: var(--body-bg);
}

View File

@ -139,12 +139,6 @@
margin: 0 0 0 30px; margin: 0 0 0 30px;
} }
@media (forced-colors: active) {
#changelist-filter {
border: 1px solid;
}
}
#changelist-filter h2 { #changelist-filter h2 {
font-size: 0.875rem; font-size: 0.875rem;
text-transform: uppercase; text-transform: uppercase;
@ -221,9 +215,9 @@
color: var(--link-hover-color); color: var(--link-hover-color);
} }
#changelist-filter #changelist-filter-extra-actions { #changelist-filter #changelist-filter-clear a {
font-size: 0.8125rem; font-size: 0.8125rem;
margin-bottom: 10px; padding-bottom: 10px;
border-bottom: 1px solid var(--hairline-color); border-bottom: 1px solid var(--hairline-color);
} }
@ -271,15 +265,6 @@
background-color: var(--selected-row); background-color: var(--selected-row);
} }
@media (forced-colors: active) {
#changelist tbody tr.selected {
background-color: SelectedItem;
}
#changelist tbody tr:has(.action-select:checked) {
background-color: SelectedItem;
}
}
#changelist .actions { #changelist .actions {
padding: 10px; padding: 10px;
background: var(--body-bg); background: var(--body-bg);

View File

@ -5,8 +5,7 @@
--body-fg: #eeeeee; --body-fg: #eeeeee;
--body-bg: #121212; --body-bg: #121212;
--body-quiet-color: #d0d0d0; --body-quiet-color: #e0e0e0;
--body-medium-color: #e0e0e0;
--body-loud-color: #ffffff; --body-loud-color: #ffffff;
--breadcrumbs-link-fg: #e0e0e0; --breadcrumbs-link-fg: #e0e0e0;
@ -30,8 +29,6 @@
--close-button-bg: #333333; --close-button-bg: #333333;
--close-button-hover-bg: #666666; --close-button-hover-bg: #666666;
color-scheme: dark;
} }
} }
@ -42,8 +39,7 @@ html[data-theme="dark"] {
--body-fg: #eeeeee; --body-fg: #eeeeee;
--body-bg: #121212; --body-bg: #121212;
--body-quiet-color: #d0d0d0; --body-quiet-color: #e0e0e0;
--body-medium-color: #e0e0e0;
--body-loud-color: #ffffff; --body-loud-color: #ffffff;
--breadcrumbs-link-fg: #e0e0e0; --breadcrumbs-link-fg: #e0e0e0;
@ -67,8 +63,6 @@ html[data-theme="dark"] {
--close-button-bg: #333333; --close-button-bg: #333333;
--close-button-hover-bg: #666666; --close-button-hover-bg: #666666;
color-scheme: dark;
} }
/* THEME SWITCH */ /* THEME SWITCH */
@ -128,3 +122,16 @@ html[data-theme="dark"] .theme-toggle svg.theme-icon-when-dark {
html[data-theme="light"] .theme-toggle svg.theme-icon-when-light { html[data-theme="light"] .theme-toggle svg.theme-icon-when-light {
display: block; display: block;
} }
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
border: 0;
color: var(--body-fg);
background-color: var(--body-bg);
}

View File

@ -44,6 +44,7 @@ label {
.required label, label.required { .required label, label.required {
font-weight: bold; font-weight: bold;
color: var(--body-fg);
} }
/* RADIO BUTTONS */ /* RADIO BUTTONS */
@ -75,20 +76,6 @@ form ul.inline li {
padding-right: 7px; padding-right: 7px;
} }
/* FIELDSETS */
fieldset .fieldset-heading,
fieldset .inline-heading,
:not(.inline-related) .collapse summary {
border: 1px solid var(--header-bg);
margin: 0;
padding: 8px;
font-weight: 400;
font-size: 0.8125rem;
background: var(--header-bg);
color: var(--header-link-color);
}
/* ALIGNED FIELDSETS */ /* ALIGNED FIELDSETS */
.aligned label { .aligned label {
@ -97,12 +84,14 @@ fieldset .inline-heading,
min-width: 160px; min-width: 160px;
width: 160px; width: 160px;
word-wrap: break-word; word-wrap: break-word;
line-height: 1;
} }
.aligned label:not(.vCheckboxLabel):after { .aligned label:not(.vCheckboxLabel):after {
content: ''; content: '';
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
height: 1.625rem;
} }
.aligned label + p, .aligned .checkbox-row + div.help, .aligned label + div.readonly { .aligned label + p, .aligned .checkbox-row + div.help, .aligned label + div.readonly {
@ -169,10 +158,6 @@ form .aligned select + div.help {
padding-left: 10px; padding-left: 10px;
} }
form .aligned select option:checked {
background-color: var(--selected-row);
}
form .aligned ul li { form .aligned ul li {
list-style: none; list-style: none;
} }
@ -183,7 +168,11 @@ form .aligned table p {
} }
.aligned .vCheckboxLabel { .aligned .vCheckboxLabel {
padding: 1px 0 0 5px; float: none;
width: auto;
display: inline-block;
vertical-align: -3px;
padding: 0 0 5px 5px;
} }
.aligned .vCheckboxLabel + p.help, .aligned .vCheckboxLabel + p.help,
@ -205,8 +194,14 @@ fieldset .fieldBox {
width: 200px; width: 200px;
} }
form .wide p.help, form .wide p,
form .wide ul.errorlist, form .wide ul.errorlist,
form .wide input + p.help,
form .wide input + div.help {
margin-left: 200px;
}
form .wide p.help,
form .wide div.help { form .wide div.help {
padding-left: 50px; padding-left: 50px;
} }
@ -220,16 +215,35 @@ form div.help ul {
width: 450px; width: 450px;
} }
/* COLLAPSIBLE FIELDSETS */ /* COLLAPSED FIELDSETS */
.collapse summary .fieldset-heading, fieldset.collapsed * {
.collapse summary .inline-heading { display: none;
}
fieldset.collapsed h2, fieldset.collapsed {
display: block;
}
fieldset.collapsed {
border: 1px solid var(--hairline-color);
border-radius: 4px;
overflow: hidden;
}
fieldset.collapsed h2 {
background: var(--darkened-bg);
color: var(--body-quiet-color);
}
fieldset .collapse-toggle {
color: var(--header-link-color);
}
fieldset.collapsed .collapse-toggle {
background: transparent; background: transparent;
border: none;
color: currentColor;
display: inline; display: inline;
margin: 0; color: var(--link-fg);
padding: 0;
} }
/* MONOSPACE TEXTAREAS */ /* MONOSPACE TEXTAREAS */
@ -381,16 +395,14 @@ body.popup .submit-row {
position: relative; position: relative;
} }
.inline-related h4, .inline-related h3 {
.inline-related:not(.tabular) .collapse summary {
margin: 0; margin: 0;
color: var(--body-medium-color); color: var(--body-quiet-color);
padding: 5px; padding: 5px;
font-size: 0.8125rem; font-size: 0.8125rem;
background: var(--darkened-bg); background: var(--darkened-bg);
border: 1px solid var(--hairline-color); border-top: 1px solid var(--hairline-color);
border-left-color: var(--darkened-bg); border-bottom: 1px solid var(--hairline-color);
border-right-color: var(--darkened-bg);
} }
.inline-related h3 span.delete { .inline-related h3 span.delete {
@ -409,6 +421,16 @@ body.popup .submit-row {
width: 100%; width: 100%;
} }
.inline-related fieldset.module h3 {
margin: 0;
padding: 2px 5px 3px 5px;
font-size: 0.6875rem;
text-align: left;
font-weight: bold;
background: #bcd;
color: var(--body-bg);
}
.inline-group .tabular fieldset.module { .inline-group .tabular fieldset.module {
border: none; border: none;
} }

View File

@ -21,7 +21,7 @@
} }
.login #content { .login #content {
padding: 20px; padding: 20px 20px 0;
} }
.login #container { .login #container {

View File

@ -102,12 +102,6 @@
background: var(--selected-row); background: var(--selected-row);
} }
@media (forced-colors: active) {
#nav-sidebar .current-model {
background-color: SelectedItem;
}
}
.main > #nav-sidebar + .content { .main > #nav-sidebar + .content {
max-width: calc(100% - 23px); max-width: calc(100% - 23px);
} }

View File

@ -43,7 +43,7 @@ input[type="submit"], button {
justify-content: flex-start; justify-content: flex-start;
} }
#site-name { #branding h1 {
margin: 0 0 8px; margin: 0 0 8px;
line-height: 1.2; line-height: 1.2;
} }
@ -171,14 +171,9 @@ input[type="submit"], button {
/* Forms */ /* Forms */
label { label {
font-size: 1rem; font-size: 0.875rem;
} }
/*
Minifiers remove the default (text) "type" attribute from "input" HTML
tags. Add input:not([type]) to make the CSS stylesheet work the same.
*/
.form-row input:not([type]),
.form-row input[type=text], .form-row input[type=text],
.form-row input[type=password], .form-row input[type=password],
.form-row input[type=email], .form-row input[type=email],
@ -192,7 +187,7 @@ input[type="submit"], button {
margin: 0; margin: 0;
padding: 6px 8px; padding: 6px 8px;
min-height: 2.25rem; min-height: 2.25rem;
font-size: 1rem; font-size: 0.875rem;
} }
.form-row select { .form-row select {
@ -242,6 +237,22 @@ input[type="submit"], button {
padding: 7px; padding: 7px;
} }
/* Related widget */
.related-widget-wrapper {
float: none;
}
.related-widget-wrapper-link + .selector {
max-width: calc(100% - 30px);
margin-right: 15px;
}
select + .related-widget-wrapper-link,
.related-widget-wrapper-link + .related-widget-wrapper-link {
margin-left: 10px;
}
/* Selector */ /* Selector */
.selector { .selector {
@ -259,7 +270,7 @@ input[type="submit"], button {
} }
.selector .selector-filter input { .selector .selector-filter input {
width: 100%; width: auto;
min-height: 0; min-height: 0;
flex: 1 1; flex: 1 1;
} }
@ -281,6 +292,7 @@ input[type="submit"], button {
width: 26px; width: 26px;
height: 52px; height: 52px;
padding: 2px 0; padding: 2px 0;
margin: auto 15px;
border-radius: 20px; border-radius: 20px;
transform: translateY(-10px); transform: translateY(-10px);
} }
@ -324,6 +336,7 @@ input[type="submit"], button {
width: 52px; width: 52px;
height: 26px; height: 26px;
padding: 0 2px; padding: 0 2px;
margin: 15px auto;
transform: none; transform: none;
} }
@ -419,7 +432,7 @@ input[type="submit"], button {
padding: 15px 20px; padding: 15px 20px;
} }
.login #site-name { .login #branding h1 {
margin: 0; margin: 0;
} }
@ -451,10 +464,14 @@ input[type="submit"], button {
@media (max-width: 767px) { @media (max-width: 767px) {
/* Layout */ /* Layout */
#header, #content { #header, #content, #footer {
padding: 15px; padding: 15px;
} }
#footer:empty {
padding: 0;
}
div.breadcrumbs { div.breadcrumbs {
padding: 10px 15px; padding: 10px 15px;
} }
@ -565,6 +582,10 @@ input[type="submit"], button {
padding-top: 15px; padding-top: 15px;
} }
fieldset.collapsed .form-row {
display: none;
}
.aligned label { .aligned label {
width: 100%; width: 100%;
min-width: auto; min-width: auto;
@ -663,14 +684,23 @@ input[type="submit"], button {
align-self: center; align-self: center;
} }
select + .related-widget-wrapper-link,
.related-widget-wrapper-link + .related-widget-wrapper-link {
margin-left: 15px;
}
/* Selector */ /* Selector */
.selector { .selector {
flex-direction: column; flex-direction: column;
gap: 10px 0; }
.selector > * {
float: none;
} }
.selector-available, .selector-chosen { .selector-available, .selector-chosen {
margin-bottom: 0;
flex: 1 1 auto; flex: 1 1 auto;
} }
@ -680,9 +710,11 @@ input[type="submit"], button {
.selector ul.selector-chooser { .selector ul.selector-chooser {
display: block; display: block;
float: none;
width: 52px; width: 52px;
height: 26px; height: 26px;
padding: 0 2px; padding: 0 2px;
margin: 15px auto 20px;
transform: none; transform: none;
} }

View File

@ -35,6 +35,11 @@
background-position: calc(100% - 8px) 9px; background-position: calc(100% - 8px) 9px;
} }
[dir="rtl"] .related-widget-wrapper-link + .selector {
margin-right: 0;
margin-left: 15px;
}
[dir="rtl"] .selector .selector-filter label { [dir="rtl"] .selector .selector-filter label {
margin-right: 0; margin-right: 0;
margin-left: 8px; margin-left: 8px;
@ -53,22 +58,6 @@
padding-left: 0; padding-left: 0;
padding-right: 16px; padding-right: 16px;
} }
[dir="rtl"] .selector-add {
background-position: 0 -80px;
}
[dir="rtl"] .selector-remove {
background-position: 0 -120px;
}
[dir="rtl"] .active.selector-add:focus, .active.selector-add:hover {
background-position: 0 -100px;
}
[dir="rtl"] .active.selector-remove:focus, .active.selector-remove:hover {
background-position: 0 -140px;
}
} }
/* MOBILE */ /* MOBILE */
@ -92,20 +81,4 @@
[dir="rtl"] .aligned .vCheckboxLabel { [dir="rtl"] .aligned .vCheckboxLabel {
padding: 1px 5px 0 0; padding: 1px 5px 0 0;
} }
[dir="rtl"] .selector-remove {
background-position: 0 0;
}
[dir="rtl"] .active.selector-remove:focus, .active.selector-remove:hover {
background-position: 0 -20px;
}
[dir="rtl"] .selector-add {
background-position: 0 -40px;
}
[dir="rtl"] .active.selector-add:focus, .active.selector-add:hover {
background-position: 0 -60px;
}
} }

View File

@ -13,7 +13,7 @@ th {
margin-right: 1.5em; margin-right: 1.5em;
} }
.viewlink, .addlink, .changelink, .hidelink { .viewlink, .addlink, .changelink {
padding-left: 0; padding-left: 0;
padding-right: 16px; padding-right: 16px;
background-position: 100% 1px; background-position: 100% 1px;
@ -151,7 +151,6 @@ form ul.inline li {
form .aligned p.help, form .aligned p.help,
form .aligned div.help { form .aligned div.help {
margin-left: 0;
margin-right: 160px; margin-right: 160px;
padding-right: 10px; padding-right: 10px;
} }
@ -165,13 +164,19 @@ form .aligned p.time div.help.timezonewarning {
padding-right: 0; padding-right: 0;
} }
form .wide p.help, form .wide p.help, form .wide div.help {
form .wide ul.errorlist,
form .wide div.help {
padding-left: 0; padding-left: 0;
padding-right: 50px; padding-right: 50px;
} }
form .wide p,
form .wide ul.errorlist,
form .wide input + p.help,
form .wide input + div.help {
margin-right: 200px;
margin-left: 0px;
}
.submit-row { .submit-row {
text-align: right; text-align: right;
} }
@ -197,7 +202,12 @@ fieldset .fieldBox {
top: 0; top: 0;
left: auto; left: auto;
right: 10px; right: 10px;
background: url(../img/calendar-icons.svg) 0 -15px no-repeat; background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
}
.calendarbox .calendarnav-previous:focus,
.calendarbox .calendarnav-previous:hover {
background-position: 0 -45px;
} }
.calendarnav-next { .calendarnav-next {
@ -207,6 +217,11 @@ fieldset .fieldBox {
background: url(../img/calendar-icons.svg) 0 0 no-repeat; background: url(../img/calendar-icons.svg) 0 0 no-repeat;
} }
.calendarbox .calendarnav-next:focus,
.calendarbox .calendarnav-next:hover {
background-position: 0 -15px;
}
.calendar caption, .calendarbox h2 { .calendar caption, .calendarbox h2 {
text-align: center; text-align: center;
} }
@ -281,11 +296,3 @@ form .form-row p.datetime {
margin-left: inherit; margin-left: inherit;
margin-right: 2px; margin-right: 2px;
} }
.inline-group .tabular td.original p {
right: 0;
}
.selector .selector-chooser {
margin: 0;
}

View File

@ -1,23 +1,23 @@
/* SELECTOR (FILTER INTERFACE) */ /* SELECTOR (FILTER INTERFACE) */
.selector { .selector {
width: 800px;
float: left;
display: flex; display: flex;
flex-grow: 1;
gap: 0 10px;
} }
.selector select { .selector select {
width: 380px;
height: 17.2em; height: 17.2em;
flex: 1 0 auto; flex: 1 0 auto;
overflow: scroll;
width: 100%;
} }
.selector-available, .selector-chosen { .selector-available, .selector-chosen {
width: 380px;
text-align: center; text-align: center;
margin-bottom: 5px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1 1;
} }
.selector-available h2, .selector-chosen h2 { .selector-available h2, .selector-chosen h2 {
@ -41,7 +41,7 @@
} }
.selector-chosen h2 { .selector-chosen h2 {
background: var(--secondary); background: var(--primary);
color: var(--header-link-color); color: var(--header-link-color);
} }
@ -58,7 +58,6 @@
font-size: 0.625rem; font-size: 0.625rem;
margin: 0; margin: 0;
text-align: left; text-align: left;
display: flex;
} }
.selector .selector-filter label, .selector .selector-filter label,
@ -73,12 +72,9 @@
min-width: auto; min-width: auto;
} }
.selector-filter input {
flex-grow: 1;
}
.selector .selector-available input, .selector .selector-available input,
.selector .selector-chosen input { .selector .selector-chosen input {
width: 320px;
margin-left: 8px; margin-left: 8px;
} }
@ -87,7 +83,7 @@
width: 22px; width: 22px;
background-color: var(--selected-bg); background-color: var(--selected-bg);
border-radius: 10px; border-radius: 10px;
margin: 0; margin: 0 5px;
padding: 0; padding: 0;
transform: translateY(-17px); transform: translateY(-17px);
} }
@ -151,7 +147,7 @@ a.selector-chooseall, a.selector-clearall {
display: inline-block; display: inline-block;
height: 16px; height: 16px;
text-align: left; text-align: left;
margin: 0 auto; margin: 1px auto 3px;
overflow: hidden; overflow: hidden;
font-weight: bold; font-weight: bold;
line-height: 16px; line-height: 16px;
@ -451,7 +447,7 @@ span.clearable-file-input label {
} }
.calendar td.selected a { .calendar td.selected a {
background: var(--secondary); background: var(--primary);
color: var(--button-fg); color: var(--button-fg);
} }
@ -519,26 +515,36 @@ span.clearable-file-input label {
background: url(../img/calendar-icons.svg) 0 0 no-repeat; background: url(../img/calendar-icons.svg) 0 0 no-repeat;
} }
.calendarbox .calendarnav-previous:focus,
.calendarbox .calendarnav-previous:hover {
background-position: 0 -15px;
}
.calendarnav-next { .calendarnav-next {
right: 10px; right: 10px;
background: url(../img/calendar-icons.svg) 0 -15px no-repeat; background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
}
.calendarbox .calendarnav-next:focus,
.calendarbox .calendarnav-next:hover {
background-position: 0 -45px;
} }
.calendar-cancel { .calendar-cancel {
margin: 0; margin: 0;
padding: 4px 0; padding: 4px 0;
font-size: 0.75rem; font-size: 0.75rem;
background: var(--close-button-bg); background: #eee;
border-top: 1px solid var(--border-color); border-top: 1px solid var(--border-color);
color: var(--button-fg); color: var(--body-fg);
} }
.calendar-cancel:focus, .calendar-cancel:hover { .calendar-cancel:focus, .calendar-cancel:hover {
background: var(--close-button-hover-bg); background: #ddd;
} }
.calendar-cancel a { .calendar-cancel a {
color: var(--button-fg); color: black;
display: block; display: block;
} }
@ -569,21 +575,26 @@ ul.timelist, .timelist li {
/* RELATED WIDGET WRAPPER */ /* RELATED WIDGET WRAPPER */
.related-widget-wrapper { .related-widget-wrapper {
display: flex; float: left; /* display properly in form rows with multiple fields */
gap: 0 10px; overflow: hidden; /* clear floated contents */
flex-grow: 1;
flex-wrap: wrap;
margin-bottom: 5px;
} }
.related-widget-wrapper-link { .related-widget-wrapper-link {
opacity: .6; opacity: 0.3;
filter: grayscale(1);
} }
.related-widget-wrapper-link:link { .related-widget-wrapper-link:link {
opacity: .8;
}
.related-widget-wrapper-link:link:focus,
.related-widget-wrapper-link:link:hover {
opacity: 1; opacity: 1;
filter: grayscale(0); }
select + .related-widget-wrapper-link,
.related-widget-wrapper-link + .related-widget-wrapper-link {
margin-left: 7px;
} }
/* GIS MAPS */ /* GIS MAPS */

View File

@ -1,4 +1,4 @@
All icons are taken from Font Awesome (https://fontawesome.com/) project. All icons are taken from Font Awesome (http://fontawesome.io/) project.
The Font Awesome font is licensed under the SIL OFL 1.1: The Font Awesome font is licensed under the SIL OFL 1.1:
- https://scripts.sil.org/OFL - https://scripts.sil.org/OFL

View File

@ -1,63 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg width="15" height="60" viewBox="0 0 1792 7168" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg <defs>
width="15" <g id="previous">
height="30" <path d="M1037 1395l102-102q19-19 19-45t-19-45l-307-307 307-307q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-454 454q-19 19-19 45t19 45l454 454q19 19 45 19t45-19zm627-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
viewBox="0 0 1792 3584"
version="1.1"
id="svg5"
sodipodi:docname="calendar-icons.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="13.3"
inkscape:cx="15.526316"
inkscape:cy="20.977444"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg5" />
<defs
id="defs2">
<g
id="previous">
<path
d="m 1037,1395 102,-102 q 19,-19 19,-45 0,-26 -19,-45 L 832,896 1139,589 q 19,-19 19,-45 0,-26 -19,-45 L 1037,397 q -19,-19 -45,-19 -26,0 -45,19 L 493,851 q -19,19 -19,45 0,26 19,45 l 454,454 q 19,19 45,19 26,0 45,-19 z m 627,-499 q 0,209 -103,385.5 Q 1458,1458 1281.5,1561 1105,1664 896,1664 687,1664 510.5,1561 334,1458 231,1281.5 128,1105 128,896 128,687 231,510.5 334,334 510.5,231 687,128 896,128 1105,128 1281.5,231 1458,334 1561,510.5 1664,687 1664,896 Z"
id="path1" />
</g> </g>
<g <g id="next">
id="next"> <path d="M845 1395l454-454q19-19 19-45t-19-45l-454-454q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l307 307-307 307q-19 19-19 45t19 45l102 102q19 19 45 19t45-19zm819-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
<path
d="m 845,1395 454,-454 q 19,-19 19,-45 0,-26 -19,-45 L 845,397 q -19,-19 -45,-19 -26,0 -45,19 L 653,499 q -19,19 -19,45 0,26 19,45 l 307,307 -307,307 q -19,19 -19,45 0,26 19,45 l 102,102 q 19,19 45,19 26,0 45,-19 z m 819,-499 q 0,209 -103,385.5 Q 1458,1458 1281.5,1561 1105,1664 896,1664 687,1664 510.5,1561 334,1458 231,1281.5 128,1105 128,896 128,687 231,510.5 334,334 510.5,231 687,128 896,128 1105,128 1281.5,231 1458,334 1561,510.5 1664,687 1664,896 Z"
id="path2" />
</g> </g>
</defs> </defs>
<use <use xlink:href="#previous" x="0" y="0" fill="#333333" />
xlink:href="#next" <use xlink:href="#previous" x="0" y="1792" fill="#000000" />
x="0" <use xlink:href="#next" x="0" y="3584" fill="#333333" />
y="5376" <use xlink:href="#next" x="0" y="5376" fill="#000000" />
fill="#000000"
id="use5"
transform="translate(0,-3584)" />
<use
xlink:href="#previous"
x="0"
y="0"
fill="#333333"
id="use2"
style="fill:#000000;fill-opacity:1" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,3 +1,3 @@
<svg width="13" height="13" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"> <svg width="13" height="13" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
<path fill="#5fa225" d="M1600 796v192q0 40-28 68t-68 28h-416v416q0 40-28 68t-68 28h-192q-40 0-68-28t-28-68v-416h-416q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h416v-416q0-40 28-68t68-28h192q40 0 68 28t28 68v416h416q40 0 68 28t28 68z"/> <path fill="#70bf2b" d="M1600 796v192q0 40-28 68t-68 28h-416v416q0 40-28 68t-68 28h-192q-40 0-68-28t-28-68v-416h-416q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h416v-416q0-40 28-68t68-28h192q40 0 68 28t28 68v416h416q40 0 68 28t28 68z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 331 B

After

Width:  |  Height:  |  Size: 331 B

View File

@ -1,3 +1,3 @@
<svg width="13" height="13" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"> <svg width="13" height="13" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
<path fill="#b48c08" d="M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z"/> <path fill="#efb80b" d="M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 380 B

After

Width:  |  Height:  |  Size: 380 B

View File

@ -1,4 +1,4 @@
/*global SelectBox, gettext, ngettext, interpolate, quickElement, SelectFilter*/ /*global SelectBox, gettext, interpolate, quickElement, SelectFilter*/
/* /*
SelectFilter2 - Turns a multiple-select box into a filter interface. SelectFilter2 - Turns a multiple-select box into a filter interface.
@ -30,9 +30,6 @@ Requires core.js and SelectBox.js.
// <div class="selector"> or <div class="selector stacked"> // <div class="selector"> or <div class="selector stacked">
const selector_div = quickElement('div', from_box.parentNode); const selector_div = quickElement('div', from_box.parentNode);
// Make sure the selector div is at the beginning so that the
// add link would be displayed to the right of the widget.
from_box.parentNode.prepend(selector_div);
selector_div.className = is_stacked ? 'selector stacked' : 'selector'; selector_div.className = is_stacked ? 'selector stacked' : 'selector';
// <div class="selector-available"> // <div class="selector-available">

View File

@ -1,4 +1,4 @@
/*global gettext, interpolate, ngettext, Actions*/ /*global gettext, interpolate, ngettext*/
'use strict'; 'use strict';
{ {
function show(selector) { function show(selector) {
@ -179,9 +179,6 @@
} }
}); });
} }
// Sync counter when navigating to the page, such as through the back
// button.
window.addEventListener('pageshow', (event) => updateCounter(actionCheckboxes, options));
}; };
// Call function fn when the DOM is loaded and ready. If it is already // Call function fn when the DOM is loaded and ready. If it is already

View File

@ -79,11 +79,9 @@
siblings.each(function() { siblings.each(function() {
const elm = $(this); const elm = $(this);
elm.attr('href', elm.attr('data-href-template').replace('__fk__', value)); elm.attr('href', elm.attr('data-href-template').replace('__fk__', value));
elm.removeAttr('aria-disabled');
}); });
} else { } else {
siblings.removeAttr('href'); siblings.removeAttr('href');
siblings.attr('aria-disabled', true);
} }
} }
@ -96,8 +94,8 @@
// Extract the model from the popup url '.../<model>/add/' or // Extract the model from the popup url '.../<model>/add/' or
// '.../<model>/<id>/change/' depending the action (add or change). // '.../<model>/<id>/change/' depending the action (add or change).
const modelName = path.split('/')[path.split('/').length - (objId ? 4 : 3)]; const modelName = path.split('/')[path.split('/').length - (objId ? 4 : 3)];
// Select elements with a specific model reference and context of "available-source". // Exclude autocomplete selects.
const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] [data-context="available-source"]`); const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] select:not(.admin-autocomplete)`);
selectsRelated.forEach(function(select) { selectsRelated.forEach(function(select) {
if (currentSelect === select) { if (currentSelect === select) {

View File

@ -36,24 +36,6 @@ depends on core.js for utility functions like removeChildren or quickElement
pgettext('abbrev. month December', 'Dec') pgettext('abbrev. month December', 'Dec')
], ],
daysOfWeek: [ daysOfWeek: [
gettext('Sunday'),
gettext('Monday'),
gettext('Tuesday'),
gettext('Wednesday'),
gettext('Thursday'),
gettext('Friday'),
gettext('Saturday')
],
daysOfWeekAbbrev: [
pgettext('abbrev. day Sunday', 'Sun'),
pgettext('abbrev. day Monday', 'Mon'),
pgettext('abbrev. day Tuesday', 'Tue'),
pgettext('abbrev. day Wednesday', 'Wed'),
pgettext('abbrev. day Thursday', 'Thur'),
pgettext('abbrev. day Friday', 'Fri'),
pgettext('abbrev. day Saturday', 'Sat')
],
daysOfWeekInitial: [
pgettext('one letter Sunday', 'S'), pgettext('one letter Sunday', 'S'),
pgettext('one letter Monday', 'M'), pgettext('one letter Monday', 'M'),
pgettext('one letter Tuesday', 'T'), pgettext('one letter Tuesday', 'T'),
@ -116,7 +98,7 @@ depends on core.js for utility functions like removeChildren or quickElement
// Draw days-of-week header // Draw days-of-week header
let tableRow = quickElement('tr', tableBody); let tableRow = quickElement('tr', tableBody);
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
quickElement('th', tableRow, CalendarNamespace.daysOfWeekInitial[(i + CalendarNamespace.firstDayOfWeek) % 7]); quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]);
} }
const startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); const startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay();

View File

@ -85,18 +85,6 @@ function findPosY(obj) {
return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds(); return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
}; };
Date.prototype.getAbbrevDayName = function() {
return typeof window.CalendarNamespace === "undefined"
? '0' + this.getDay()
: window.CalendarNamespace.daysOfWeekAbbrev[this.getDay()];
};
Date.prototype.getFullDayName = function() {
return typeof window.CalendarNamespace === "undefined"
? '0' + this.getDay()
: window.CalendarNamespace.daysOfWeek[this.getDay()];
};
Date.prototype.getAbbrevMonthName = function() { Date.prototype.getAbbrevMonthName = function() {
return typeof window.CalendarNamespace === "undefined" return typeof window.CalendarNamespace === "undefined"
? this.getTwoDigitMonth() ? this.getTwoDigitMonth()
@ -111,8 +99,6 @@ function findPosY(obj) {
Date.prototype.strftime = function(format) { Date.prototype.strftime = function(format) {
const fields = { const fields = {
a: this.getAbbrevDayName(),
A: this.getFullDayName(),
b: this.getAbbrevMonthName(), b: this.getAbbrevMonthName(),
B: this.getFullMonthName(), B: this.getFullMonthName(),
c: this.toString(), c: this.toString(),

View File

@ -1,3 +1,4 @@
/*global opener */
'use strict'; 'use strict';
{ {
const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse); const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);

View File

@ -1,51 +1,56 @@
'use strict'; 'use strict';
{ {
function setTheme(mode) { window.addEventListener('load', function(e) {
if (mode !== "light" && mode !== "dark" && mode !== "auto") {
console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);
mode = "auto";
}
document.documentElement.dataset.theme = mode;
localStorage.setItem("theme", mode);
}
function cycleTheme() { function setTheme(mode) {
const currentTheme = localStorage.getItem("theme") || "auto"; if (mode !== "light" && mode !== "dark" && mode !== "auto") {
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);
mode = "auto";
if (prefersDark) {
// Auto (dark) -> Light -> Dark
if (currentTheme === "auto") {
setTheme("light");
} else if (currentTheme === "light") {
setTheme("dark");
} else {
setTheme("auto");
} }
} else { document.documentElement.dataset.theme = mode;
// Auto (light) -> Dark -> Light localStorage.setItem("theme", mode);
if (currentTheme === "auto") { }
setTheme("dark");
} else if (currentTheme === "dark") { function cycleTheme() {
setTheme("light"); const currentTheme = localStorage.getItem("theme") || "auto";
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
if (prefersDark) {
// Auto (dark) -> Light -> Dark
if (currentTheme === "auto") {
setTheme("light");
} else if (currentTheme === "light") {
setTheme("dark");
} else {
setTheme("auto");
}
} else { } else {
setTheme("auto"); // Auto (light) -> Dark -> Light
if (currentTheme === "auto") {
setTheme("dark");
} else if (currentTheme === "dark") {
setTheme("light");
} else {
setTheme("auto");
}
} }
} }
}
function initTheme() { function initTheme() {
// set theme defined in localStorage if there is one, or fallback to auto mode // set theme defined in localStorage if there is one, or fallback to auto mode
const currentTheme = localStorage.getItem("theme"); const currentTheme = localStorage.getItem("theme");
currentTheme ? setTheme(currentTheme) : setTheme("auto"); currentTheme ? setTheme(currentTheme) : setTheme("auto");
} }
window.addEventListener('load', function(_) { function setupTheme() {
const buttons = document.getElementsByClassName("theme-toggle"); // Attach event handlers for toggling themes
Array.from(buttons).forEach((btn) => { const buttons = document.getElementsByClassName("theme-toggle");
btn.addEventListener("click", cycleTheme); Array.from(buttons).forEach((btn) => {
}); btn.addEventListener("click", cycleTheme);
});
initTheme();
}
setupTheme();
}); });
initTheme();
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
The MIT License The MIT License
Copyright (c) 2007-present Steven Levithan <http://xregexp.com/> Copyright (c) 2007-2017 Steven Levithan <http://xregexp.com/>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,4 @@
@font-face {
font-family: 'SaudiRiyalFont';
src: url('/static/assets/fonts/SaudiRiyalFont.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
.currency {
font-family: 'SaudiRiyalFont', sans-serif;
}
.color-div { .color-div {
width: 64px; width: 64px;

View File

@ -3781,7 +3781,6 @@ textarea.form-control-lg {
.form-select { .form-select {
--phoenix-form-select-bg-img: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjE1MCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik03NS4zNDggMTI3LjE5MkM3Mi40MzgxIDEyNy4xOTIgNjkuODUxNCAxMjYuMjIyIDY3LjkxMTUgMTI0LjI4Mkw1LjgzMjE1IDYyLjIwMjNDMS42Mjg4NyA1OC4zMjIzIDEuNjI4ODcgNTEuNTMyNCA1LjgzMjE1IDQ3LjY1MjVDOS43MTIxMSA0My40NDkyIDE2LjUwMiA0My40NDkyIDIwLjM4MiA0Ny42NTI1TDc1LjM0OCAxMDIuMjk1TDEyOS45OTEgNDcuNjUyNUMxMzMuODcxIDQzLjQ0OTIgMTQwLjY2MSA0My40NDkyIDE0NC41NDEgNDcuNjUyNUMxNDguNzQ0IDUxLjUzMjQgMTQ4Ljc0NCA1OC4zMjIzIDE0NC41NDEgNjIuMjAyM0w4Mi40NjEzIDEyNC4yODJDODAuNTIxMyAxMjYuMjIyIDc3LjkzNDcgMTI3LjE5MiA3NS4zNDggMTI3LjE5MloiIGZpbGw9IiMzMTM3NEEiLz4KPC9zdmc+Cg=="); --phoenix-form-select-bg-img: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjE1MCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik03NS4zNDggMTI3LjE5MkM3Mi40MzgxIDEyNy4xOTIgNjkuODUxNCAxMjYuMjIyIDY3LjkxMTUgMTI0LjI4Mkw1LjgzMjE1IDYyLjIwMjNDMS42Mjg4NyA1OC4zMjIzIDEuNjI4ODcgNTEuNTMyNCA1LjgzMjE1IDQ3LjY1MjVDOS43MTIxMSA0My40NDkyIDE2LjUwMiA0My40NDkyIDIwLjM4MiA0Ny42NTI1TDc1LjM0OCAxMDIuMjk1TDEyOS45OTEgNDcuNjUyNUMxMzMuODcxIDQzLjQ0OTIgMTQwLjY2MSA0My40NDkyIDE0NC41NDEgNDcuNjUyNUMxNDguNzQ0IDUxLjUzMjQgMTQ4Ljc0NCA1OC4zMjIzIDE0NC41NDEgNjIuMjAyM0w4Mi40NjEzIDEyNC4yODJDODAuNTIxMyAxMjYuMjIyIDc3LjkzNDcgMTI3LjE5MiA3NS4zNDggMTI3LjE5MloiIGZpbGw9IiMzMTM3NEEiLz4KPC9zdmc+Cg==");
display: block; display: block;
text-align: start;
width: 100%; width: 100%;
padding: 0.5rem 1rem 0.5rem 2.5rem; padding: 0.5rem 1rem 0.5rem 2.5rem;
font-size: 0.8rem; font-size: 0.8rem;
@ -4700,7 +4699,6 @@ textarea.form-control-lg {
top: 100%; top: 100%;
right: 0; right: 0;
margin-top: var(--phoenix-dropdown-spacer); margin-top: var(--phoenix-dropdown-spacer);
text-align: right;
} }
.dropdown-menu-start { .dropdown-menu-start {

View File

@ -1259,7 +1259,6 @@ progress {
font-weight: 600; font-weight: 600;
} }
.display-1 { .display-1 {
font-size: calc(1.6018371582rem + 4.2220458984vw); font-size: calc(1.6018371582rem + 4.2220458984vw);
font-weight: 400; font-weight: 400;
@ -3785,7 +3784,6 @@ textarea.form-control-lg {
--phoenix-form-select-bg-img: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjE1MCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik03NS4zNDggMTI3LjE5MkM3Mi40MzgxIDEyNy4xOTIgNjkuODUxNCAxMjYuMjIyIDY3LjkxMTUgMTI0LjI4Mkw1LjgzMjE1IDYyLjIwMjNDMS42Mjg4NyA1OC4zMjIzIDEuNjI4ODcgNTEuNTMyNCA1LjgzMjE1IDQ3LjY1MjVDOS43MTIxMSA0My40NDkyIDE2LjUwMiA0My40NDkyIDIwLjM4MiA0Ny42NTI1TDc1LjM0OCAxMDIuMjk1TDEyOS45OTEgNDcuNjUyNUMxMzMuODcxIDQzLjQ0OTIgMTQwLjY2MSA0My40NDkyIDE0NC41NDEgNDcuNjUyNUMxNDguNzQ0IDUxLjUzMjQgMTQ4Ljc0NCA1OC4zMjIzIDE0NC41NDEgNjIuMjAyM0w4Mi40NjEzIDEyNC4yODJDODAuNTIxMyAxMjYuMjIyIDc3LjkzNDcgMTI3LjE5MiA3NS4zNDggMTI3LjE5MloiIGZpbGw9IiMzMTM3NEEiLz4KPC9zdmc+Cg=="); --phoenix-form-select-bg-img: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjE1MCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik03NS4zNDggMTI3LjE5MkM3Mi40MzgxIDEyNy4xOTIgNjkuODUxNCAxMjYuMjIyIDY3LjkxMTUgMTI0LjI4Mkw1LjgzMjE1IDYyLjIwMjNDMS42Mjg4NyA1OC4zMjIzIDEuNjI4ODcgNTEuNTMyNCA1LjgzMjE1IDQ3LjY1MjVDOS43MTIxMSA0My40NDkyIDE2LjUwMiA0My40NDkyIDIwLjM4MiA0Ny42NTI1TDc1LjM0OCAxMDIuMjk1TDEyOS45OTEgNDcuNjUyNUMxMzMuODcxIDQzLjQ0OTIgMTQwLjY2MSA0My40NDkyIDE0NC41NDEgNDcuNjUyNUMxNDguNzQ0IDUxLjUzMjQgMTQ4Ljc0NCA1OC4zMjIzIDE0NC41NDEgNjIuMjAyM0w4Mi40NjEzIDEyNC4yODJDODAuNTIxMyAxMjYuMjIyIDc3LjkzNDcgMTI3LjE5MiA3NS4zNDggMTI3LjE5MloiIGZpbGw9IiMzMTM3NEEiLz4KPC9zdmc+Cg==");
display: block; display: block;
width: 100%; width: 100%;
text-align: start;
padding: 0.5rem 2.5rem 0.5rem 1rem; padding: 0.5rem 2.5rem 0.5rem 1rem;
font-size: 0.8rem; font-size: 0.8rem;
font-weight: 600; font-weight: 600;
@ -3817,7 +3815,6 @@ textarea.form-control-lg {
} }
} }
.form-select:focus { .form-select:focus {
text-align: start;
border-color: #3874ff; border-color: #3874ff;
outline: 0; outline: 0;
-webkit-box-shadow: inset 0 1px 2px transparent, 0 0 0 0.25rem rgba(56, 116, 255, 0.25); -webkit-box-shadow: inset 0 1px 2px transparent, 0 0 0 0.25rem rgba(56, 116, 255, 0.25);

View File

@ -61,7 +61,6 @@
--djdt-font-color: #8393a7; --djdt-font-color: #8393a7;
--djdt-background-color: #1e293bff; --djdt-background-color: #1e293bff;
--djdt-panel-content-background-color: #0f1729ff; --djdt-panel-content-background-color: #0f1729ff;
--djdt-panel-content-table-background-color: var(--djdt-background-color);
--djdt-panel-title-background-color: #242432; --djdt-panel-title-background-color: #242432;
--djdt-djdt-panel-content-table-strip-background-color: #324154ff; --djdt-djdt-panel-content-table-strip-background-color: #324154ff;
--djdt--highlighted-background-color: #2c2a7dff; --djdt--highlighted-background-color: #2c2a7dff;
@ -302,7 +301,7 @@
font-size: 22px; font-size: 22px;
font-weight: bold; font-weight: bold;
background: #000; background: #000;
opacity: 0.6; opacity: 0.5;
} }
#djDebug #djShowToolBarButton:hover { #djDebug #djShowToolBarButton:hover {
@ -556,94 +555,62 @@
#djDebug .highlight .err { #djDebug .highlight .err {
color: var(--djdt-font-color); color: var(--djdt-font-color);
} /* Error */ } /* Error */
#djDebug .highlight .g {
/* color: var(--djdt-font-color);
Styles for pygments HTMLFormatter } /* Generic */
#djDebug .highlight .k {
- This should match debug_toolbar/panels/templates/views.py::template_source color: var(--djdt-font-color);
- Each line needs to be prefixed with #djDebug .highlight as well. font-weight: bold;
- The .w definition needs to include: } /* Keyword */
white-space: pre-wrap #djDebug .highlight .o {
color: var(--djdt-font-color);
To regenerate: } /* Operator */
#djDebug .highlight .n {
from pygments.formatters import HtmlFormatter color: var(--djdt-font-color);
print(HtmlFormatter(wrapcode=True).get_style_defs()) } /* Name */
*/ #djDebug .highlight .mi {
#djDebug .highlight pre { line-height: 125%; } color: var(--djdt-font-color);
#djDebug .highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } font-weight: bold;
#djDebug .highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } } /* Literal.Number.Integer */
#djDebug .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } #djDebug .highlight .l {
#djDebug .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } color: var(--djdt-font-color);
#djDebug .highlight .hll { background-color: #ffffcc } } /* Literal */
#djDebug .highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ #djDebug .highlight .x {
#djDebug .highlight .err { border: 1px solid #FF0000 } /* Error */ color: var(--djdt-font-color);
#djDebug .highlight .k { color: #008000; font-weight: bold } /* Keyword */ } /* Other */
#djDebug .highlight .o { color: #666666 } /* Operator */ #djDebug .highlight .p {
#djDebug .highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ color: var(--djdt-font-color);
#djDebug .highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ } /* Punctuation */
#djDebug .highlight .cp { color: #9C6500 } /* Comment.Preproc */ #djDebug .highlight .m {
#djDebug .highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ color: var(--djdt-font-color);
#djDebug .highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ font-weight: bold;
#djDebug .highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ } /* Literal.Number */
#djDebug .highlight .gd { color: #A00000 } /* Generic.Deleted */ #djDebug .highlight .s {
#djDebug .highlight .ge { font-style: italic } /* Generic.Emph */ color: var(--djdt-template-highlight-color);
#djDebug .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ } /* Literal.String */
#djDebug .highlight .gr { color: #E40000 } /* Generic.Error */ #djDebug .highlight .w {
#djDebug .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ color: #888888;
#djDebug .highlight .gi { color: #008400 } /* Generic.Inserted */ } /* Text.Whitespace */
#djDebug .highlight .go { color: #717171 } /* Generic.Output */ #djDebug .highlight .il {
#djDebug .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ color: var(--djdt-font-color);
#djDebug .highlight .gs { font-weight: bold } /* Generic.Strong */ font-weight: bold;
#djDebug .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ } /* Literal.Number.Integer.Long */
#djDebug .highlight .gt { color: #0044DD } /* Generic.Traceback */ #djDebug .highlight .na {
#djDebug .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ color: var(--djdt-template-highlight-color);
#djDebug .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ } /* Name.Attribute */
#djDebug .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ #djDebug .highlight .nt {
#djDebug .highlight .kp { color: #008000 } /* Keyword.Pseudo */ color: var(--djdt-font-color);
#djDebug .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ font-weight: bold;
#djDebug .highlight .kt { color: #B00040 } /* Keyword.Type */ } /* Name.Tag */
#djDebug .highlight .m { color: #666666 } /* Literal.Number */ #djDebug .highlight .nv {
#djDebug .highlight .s { color: #BA2121 } /* Literal.String */ color: var(--djdt-template-highlight-color);
#djDebug .highlight .na { color: #687822 } /* Name.Attribute */ } /* Name.Variable */
#djDebug .highlight .nb { color: #008000 } /* Name.Builtin */ #djDebug .highlight .s2 {
#djDebug .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ color: var(--djdt-template-highlight-color);
#djDebug .highlight .no { color: #880000 } /* Name.Constant */ } /* Literal.String.Double */
#djDebug .highlight .nd { color: #AA22FF } /* Name.Decorator */ #djDebug .highlight .cp {
#djDebug .highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ color: var(--djdt-template-highlight-color);
#djDebug .highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ } /* Comment.Preproc */
#djDebug .highlight .nf { color: #0000FF } /* Name.Function */
#djDebug .highlight .nl { color: #767600 } /* Name.Label */
#djDebug .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
#djDebug .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
#djDebug .highlight .nv { color: #19177C } /* Name.Variable */
#djDebug .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
#djDebug .highlight .w { color: #bbbbbb; white-space: pre-wrap } /* Text.Whitespace */
#djDebug .highlight .mb { color: #666666 } /* Literal.Number.Bin */
#djDebug .highlight .mf { color: #666666 } /* Literal.Number.Float */
#djDebug .highlight .mh { color: #666666 } /* Literal.Number.Hex */
#djDebug .highlight .mi { color: #666666 } /* Literal.Number.Integer */
#djDebug .highlight .mo { color: #666666 } /* Literal.Number.Oct */
#djDebug .highlight .sa { color: #BA2121 } /* Literal.String.Affix */
#djDebug .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
#djDebug .highlight .sc { color: #BA2121 } /* Literal.String.Char */
#djDebug .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
#djDebug .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
#djDebug .highlight .s2 { color: #BA2121 } /* Literal.String.Double */
#djDebug .highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
#djDebug .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
#djDebug .highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
#djDebug .highlight .sx { color: #008000 } /* Literal.String.Other */
#djDebug .highlight .sr { color: #A45A77 } /* Literal.String.Regex */
#djDebug .highlight .s1 { color: #BA2121 } /* Literal.String.Single */
#djDebug .highlight .ss { color: #19177C } /* Literal.String.Symbol */
#djDebug .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
#djDebug .highlight .fm { color: #0000FF } /* Name.Function.Magic */
#djDebug .highlight .vc { color: #19177C } /* Name.Variable.Class */
#djDebug .highlight .vg { color: #19177C } /* Name.Variable.Global */
#djDebug .highlight .vi { color: #19177C } /* Name.Variable.Instance */
#djDebug .highlight .vm { color: #19177C } /* Name.Variable.Magic */
#djDebug .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
#djDebug svg.djDebugLineChart { #djDebug svg.djDebugLineChart {
width: 100%; width: 100%;

View File

@ -245,6 +245,7 @@
color: getColor('secondary-bg') color: getColor('secondary-bg')
} }
}, },
zlevel: 2
}, },
{ {
type: 'line', type: 'line',

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