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()