179 lines
7.4 KiB
Python
179 lines
7.4 KiB
Python
from django.core.management.base import BaseCommand
|
|
from django.db.models import Count
|
|
from inventory.models import CarMake, CarModel, CarSerie, CarTrim
|
|
import csv
|
|
import os
|
|
from django.conf import settings
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "Analyzes the car hierarchy to identify makes without models, models without series, and series without trims"
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
"--export",
|
|
action="store_true",
|
|
help="Export results to CSV files",
|
|
)
|
|
parser.add_argument(
|
|
"--export-path",
|
|
type=str,
|
|
default="exports",
|
|
help='Directory to export CSV files (default: "exports")',
|
|
)
|
|
|
|
def handle(self, *args, **options):
|
|
export = options["export"]
|
|
export_path = options["export_path"]
|
|
|
|
# Create export directory if needed
|
|
if export:
|
|
export_dir = os.path.join(settings.BASE_DIR, export_path)
|
|
if not os.path.exists(export_dir):
|
|
os.makedirs(export_dir)
|
|
|
|
# Analyze makes without models
|
|
all_makes = CarMake.objects.all()
|
|
total_makes = all_makes.count()
|
|
makes_without_models = CarMake.objects.annotate(
|
|
model_count=Count("carmodel")
|
|
).filter(model_count=0)
|
|
makes_without_models_count = makes_without_models.count()
|
|
|
|
self.stdout.write(self.style.SUCCESS(f"Total car makes: {total_makes}"))
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f"Car makes without models: {makes_without_models_count} "
|
|
f"({makes_without_models_count / total_makes * 100:.2f}% of all makes)"
|
|
)
|
|
)
|
|
|
|
if makes_without_models_count > 0:
|
|
self.stdout.write("\nSample of car makes without models:")
|
|
for make in makes_without_models[:5]:
|
|
self.stdout.write(f"- {make.name}")
|
|
|
|
# Analyze models without series
|
|
all_models = CarModel.objects.all()
|
|
total_models = all_models.count()
|
|
models_without_series = CarModel.objects.annotate(
|
|
serie_count=Count("carserie")
|
|
).filter(serie_count=0)
|
|
models_without_series_count = models_without_series.count()
|
|
|
|
self.stdout.write(self.style.SUCCESS(f"\nTotal car models: {total_models}"))
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f"Car models without series: {models_without_series_count} "
|
|
f"({models_without_series_count / total_models * 100:.2f}% of all models)"
|
|
)
|
|
)
|
|
|
|
if models_without_series_count > 0:
|
|
self.stdout.write("\nSample of car models without series:")
|
|
for model in models_without_series[:5]:
|
|
self.stdout.write(f"- {model.name} (Make: {model.id_car_make.name})")
|
|
|
|
# Analyze series without trims
|
|
all_series = CarSerie.objects.all()
|
|
total_series = all_series.count()
|
|
series_without_trims = CarSerie.objects.annotate(
|
|
trim_count=Count("cartrim")
|
|
).filter(trim_count=0)
|
|
series_without_trims_count = series_without_trims.count()
|
|
|
|
self.stdout.write(self.style.SUCCESS(f"\nTotal car series: {total_series}"))
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f"Car series without trims: {series_without_trims_count} "
|
|
f"({series_without_trims_count / total_series * 100:.2f}% of all series)"
|
|
)
|
|
)
|
|
|
|
if series_without_trims_count > 0:
|
|
self.stdout.write("\nSample of car series without trims:")
|
|
for serie in series_without_trims[:5]:
|
|
self.stdout.write(
|
|
f"- {serie.name} (Model: {serie.id_car_model.name}, "
|
|
f"Make: {serie.id_car_model.id_car_make.name})"
|
|
)
|
|
|
|
# Export data if requested
|
|
if export:
|
|
# Export makes without models
|
|
if makes_without_models_count > 0:
|
|
filepath = os.path.join(export_dir, "makes_without_models.csv")
|
|
with open(filepath, "w", newline="") as csvfile:
|
|
writer = csv.writer(csvfile)
|
|
writer.writerow(["make_id", "make_name", "is_sa_import"])
|
|
for make in makes_without_models:
|
|
writer.writerow(
|
|
[make.id_car_make, make.name, make.is_sa_import]
|
|
)
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f"Exported makes without models to {filepath}")
|
|
)
|
|
|
|
# Export models without series
|
|
if models_without_series_count > 0:
|
|
filepath = os.path.join(export_dir, "models_without_series.csv")
|
|
with open(filepath, "w", newline="") as csvfile:
|
|
writer = csv.writer(csvfile)
|
|
writer.writerow(["model_id", "model_name", "make_id", "make_name"])
|
|
for model in models_without_series:
|
|
writer.writerow(
|
|
[
|
|
model.id_car_model,
|
|
model.name,
|
|
model.id_car_make.id_car_make,
|
|
model.id_car_make.name,
|
|
]
|
|
)
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f"Exported models without series to {filepath}")
|
|
)
|
|
|
|
# Export series without trims
|
|
if series_without_trims_count > 0:
|
|
filepath = os.path.join(export_dir, "series_without_trims.csv")
|
|
with open(filepath, "w", newline="") as csvfile:
|
|
writer = csv.writer(csvfile)
|
|
writer.writerow(
|
|
[
|
|
"serie_id",
|
|
"serie_name",
|
|
"model_id",
|
|
"model_name",
|
|
"make_id",
|
|
"make_name",
|
|
]
|
|
)
|
|
for serie in series_without_trims:
|
|
writer.writerow(
|
|
[
|
|
serie.id_car_serie,
|
|
serie.name,
|
|
serie.id_car_model.id_car_model,
|
|
serie.id_car_model.name,
|
|
serie.id_car_model.id_car_make.id_car_make,
|
|
serie.id_car_model.id_car_make.name,
|
|
]
|
|
)
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f"Exported series without trims to {filepath}")
|
|
)
|
|
|
|
# Summary
|
|
self.stdout.write("\n" + "=" * 50)
|
|
self.stdout.write(self.style.SUCCESS("SUMMARY"))
|
|
self.stdout.write("=" * 50)
|
|
self.stdout.write(
|
|
f"Total makes: {total_makes} | Without models: {makes_without_models_count} ({makes_without_models_count / total_makes * 100:.2f}%)"
|
|
)
|
|
self.stdout.write(
|
|
f"Total models: {total_models} | Without series: {models_without_series_count} ({models_without_series_count / total_models * 100:.2f}%)"
|
|
)
|
|
self.stdout.write(
|
|
f"Total series: {total_series} | Without trims: {series_without_trims_count} ({series_without_trims_count / total_series * 100:.2f}%)"
|
|
)
|