You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
orquestrador/app/db/mock_seed.py

211 lines
6.8 KiB
Python

import random
from datetime import datetime
from app.core.settings import settings
from app.db.mock_database import SessionMockLocal
from app.db.mock_models import Customer, Order, RentalVehicle, Vehicle
VEHICLE_MODELS = [
"Toyota Corolla",
"Honda Civic",
"Chevrolet Onix",
"Hyundai HB20",
"Volkswagen T-Cross",
"Jeep Compass",
"Fiat Argo",
"Nissan Kicks",
"Renault Duster",
"Ford Ranger",
]
CATEGORIES = ["hatch", "sedan", "suv", "pickup"]
NAMES = [
"Ana Souza",
"Bruno Lima",
"Carla Mendes",
"Diego Santos",
"Eduarda Alves",
"Felipe Rocha",
"Gabriela Costa",
"Henrique Martins",
"Isabela Ferreira",
"Joao Ribeiro",
]
TARGET_VEHICLE_COUNT = 180
TARGET_CUSTOMER_COUNT = 320
TARGET_ORDER_COUNT = 80
VEHICLE_PRICE_BANDS = (
38990,
42990,
46990,
50990,
54990,
58990,
62990,
66990,
69990,
73990,
77990,
82990,
87990,
93990,
99990,
106990,
114990,
123990,
132990,
141990,
)
RENTAL_FLEET = [
("RAA1A01", "Chevrolet Tracker", "suv", 2024, 219.90, "disponivel"),
("RAA1A02", "Fiat Pulse", "suv", 2024, 189.90, "disponivel"),
("RAA1A03", "Volkswagen Nivus", "suv", 2024, 209.90, "disponivel"),
("RAA1A04", "Hyundai Creta", "suv", 2024, 239.90, "disponivel"),
("RAA1A05", "Jeep Renegade", "suv", 2023, 249.90, "disponivel"),
("RAA1A06", "Honda HR-V", "suv", 2024, 269.90, "disponivel"),
("RAA1A07", "Toyota Corolla Cross", "suv", 2024, 289.90, "disponivel"),
("RAA1A08", "Fiat Toro", "pickup", 2024, 319.90, "disponivel"),
("RAA1A09", "Chevrolet S10", "pickup", 2023, 369.90, "manutencao"),
("RAA1A10", "Toyota Hilux", "pickup", 2023, 429.90, "disponivel"),
("RAA1A11", "Ram Rampage", "pickup", 2024, 459.90, "disponivel"),
("RAA1A12", "Peugeot 208", "hatch", 2024, 149.90, "disponivel"),
("RAA1A13", "Renault Kwid", "hatch", 2024, 119.90, "disponivel"),
("RAA1A14", "Volkswagen Polo", "hatch", 2024, 159.90, "disponivel"),
("RAA1A15", "BYD Dolphin", "hatch", 2024, 279.90, "disponivel"),
("RAA1A16", "Toyota Yaris", "sedan", 2023, 179.90, "disponivel"),
("RAA1A17", "Honda City", "sedan", 2024, 199.90, "disponivel"),
("RAA1A18", "Nissan Versa", "sedan", 2024, 189.90, "disponivel"),
("RAA1A19", "Chevrolet Onix Plus", "sedan", 2024, 169.90, "alugado"),
("RAA1A20", "Fiat Fastback", "suv", 2024, 229.90, "disponivel"),
("RAA1A21", "Caoa Chery Tiggo 5X", "suv", 2024, 219.90, "disponivel"),
("RAA1A22", "Hyundai HB20S", "sedan", 2024, 164.90, "disponivel"),
("RAA1A23", "Jeep Compass", "suv", 2023, 309.90, "alugado"),
("RAA1A24", "Ford Maverick", "pickup", 2024, 399.90, "disponivel"),
]
def _cpf_check_digit(base_digits: str) -> str:
total = sum(int(digit) * weight for digit, weight in zip(base_digits, range(len(base_digits) + 1, 1, -1)))
remainder = 11 - (total % 11)
return "0" if remainder >= 10 else str(remainder)
def _cpf_from_index(index: int) -> str:
"""Gera um CPF valido e deterministico de 11 digitos a partir do indice."""
base_digits = f"{100_000_000 + index:09d}"[-9:]
first_digit = _cpf_check_digit(base_digits)
second_digit = _cpf_check_digit(base_digits + first_digit)
return f"{base_digits}{first_digit}{second_digit}"
def _vehicle_price_from_index(index: int, rng: random.Random) -> float:
band_price = VEHICLE_PRICE_BANDS[index % len(VEHICLE_PRICE_BANDS)]
cycle_increment = (index // len(VEHICLE_PRICE_BANDS)) * 750
noise = rng.randint(-1800, 2200)
return float(max(35000, band_price + cycle_increment + noise))
def _seed_vehicle_records(existing_count: int, target_count: int, rng: random.Random) -> list[Vehicle]:
vehicles = []
for idx in range(existing_count, target_count):
model = VEHICLE_MODELS[idx % len(VEHICLE_MODELS)]
category = CATEGORIES[idx % len(CATEGORIES)]
vehicles.append(
Vehicle(
modelo=f"{model} {2020 + (idx % 6)}",
categoria=category,
preco=_vehicle_price_from_index(idx, rng),
)
)
return vehicles
def _seed_customer_records(existing_count: int, target_count: int) -> list[Customer]:
customers = []
for idx in range(existing_count, target_count):
entropy = (idx * 9973) % 10_000
customers.append(
Customer(
cpf=_cpf_from_index(idx),
nome=f"{NAMES[idx % len(NAMES)]} {idx + 1}",
score=300 + (entropy % 550),
limite_credito=float(30_000 + (entropy * 12)),
possui_restricao=(idx % 11 == 0),
)
)
return customers
def _seed_order_records(existing_count: int, target_count: int) -> list[Order]:
orders = []
created = datetime(2026, 1, 1, 8, 0, 0)
for idx in range(existing_count, target_count):
orders.append(
Order(
numero_pedido=f"PED-MOCK-2026-{idx + 1:05d}",
cpf=_cpf_from_index(idx),
status="Ativo",
created_at=created,
)
)
return orders
def seed_mock_data() -> None:
"""Popula dados mock iniciais de veiculos, clientes e pedidos quando habilitado."""
if not settings.mock_seed_enabled:
return
rng = random.Random(42)
db = SessionMockLocal()
try:
vehicle_count = db.query(Vehicle).count()
if vehicle_count < TARGET_VEHICLE_COUNT:
vehicles = _seed_vehicle_records(
existing_count=vehicle_count,
target_count=TARGET_VEHICLE_COUNT,
rng=rng,
)
db.add_all(vehicles)
db.commit()
existing_rental_plates = {placa for (placa,) in db.query(RentalVehicle.placa).all()}
missing_rental_vehicles = [
RentalVehicle(
placa=plate,
modelo=model,
categoria=category,
ano=year,
valor_diaria=daily_rate,
status=status,
)
for plate, model, category, year, daily_rate, status in RENTAL_FLEET
if plate not in existing_rental_plates
]
if missing_rental_vehicles:
db.add_all(missing_rental_vehicles)
db.commit()
customer_count = db.query(Customer).count()
if customer_count < TARGET_CUSTOMER_COUNT:
customers = _seed_customer_records(
existing_count=customer_count,
target_count=TARGET_CUSTOMER_COUNT,
)
db.add_all(customers)
db.commit()
order_count = db.query(Order).count()
if order_count < TARGET_ORDER_COUNT:
orders = _seed_order_records(
existing_count=order_count,
target_count=TARGET_ORDER_COUNT,
)
db.add_all(orders)
db.commit()
finally:
db.close()