import asyncio import httpx import logging import os # <--- EZ HIÁNYZOTT! import datetime from sqlalchemy import select from sqlalchemy.exc import IntegrityError from app.db.session import SessionLocal from app.models.vehicle_definitions import VehicleModelDefinition from app.services.ai_service import AIService logging.basicConfig(level=logging.INFO) logger = logging.getLogger("Robot-v1.2.4-Fixed") class TechEnricher: API_URL = "https://opendata.rdw.nl/resource/kyri-nuah.json" RDW_TOKEN = os.getenv("RDW_APP_TOKEN") HEADERS = {"X-App-Token": RDW_TOKEN} if RDW_TOKEN else {} @classmethod async def fetch_rdw_tech_data(cls, make, model): """Hibatűrő RDW lekérdezés tisztított paraméterekkel.""" clean_model = str(model).strip().upper() params = {"merk": make.upper(), "handelsbenaming": clean_model, "$limit": 1} async with httpx.AsyncClient(headers=cls.HEADERS) as client: try: resp = await client.get(cls.API_URL, params=params, timeout=15) if resp.status_code == 200 and resp.json(): return resp.json()[0] return None except Exception: return None @classmethod async def run(cls): logger.info("🚀 Master Enricher INDUL (Atomi mentés üzemmód)...") # 1. Csak az ID-kat kérjük le, hogy ne tartsuk nyitva a tranzakciót feleslegesen async with SessionLocal() as main_db: stmt = select(VehicleModelDefinition.id).where( VehicleModelDefinition.status == "unverified" ).limit(50) res = await main_db.execute(stmt) ids = res.scalars().all() if not ids: logger.info("😴 Nincs dúsítandó adat.") return # 2. Egyesével dolgozzuk fel a rekordokat saját session-ben for m_id in ids: async with SessionLocal() as db: try: master = await db.get(VehicleModelDefinition, m_id) if not master: continue logger.info(f"🧪 Feldolgozás: {master.make} {master.marketing_name} (ID: {m_id})") data_found = False # A: RDW fázis rdw_data = await cls.fetch_rdw_tech_data(master.make, master.marketing_name) if rdw_data: master.engine_capacity = int(float(rdw_data.get("cilinderinhoud", 0))) or None master.power_kw = int(float(rdw_data.get("netto_maximum_vermogen_kw", 0))) or None data_found = True # B: AI fázis (ha hiányzik adat vagy pontosítani kell) if not data_found or master.engine_capacity is None: ai_data = await AIService.get_clean_vehicle_data( master.make, master.marketing_name, master.vehicle_type ) if ai_data: master.marketing_name = ai_data.get("marketing_name", master.marketing_name) master.technical_code = ai_data.get("technical_code") or master.technical_code or "N/A" master.engine_capacity = ai_data.get("ccm") or master.engine_capacity master.power_kw = ai_data.get("kw") or master.power_kw master.specifications = ai_data.get("maintenance", {}) data_found = True # C: Mentés és véglegesítés if data_found: master.status = "ai_enriched" master.updated_at = datetime.datetime.now() await db.commit() # AZONNALI COMMIT A LEMEZRE logger.info(f"✅ Sikeresen mentve: {master.marketing_name} (CCM: {master.engine_capacity})") else: logger.warning(f"⚠️ Nem találtam adatot az ID {m_id} esetében.") except IntegrityError: await db.rollback() logger.warning(f"🚫 Duplikáció vagy Constraint hiba (ID: {m_id}). Kihagyva.") except Exception as e: await db.rollback() logger.error(f"❌ Váratlan hiba az ID {m_id} esetében: {e}") finally: await db.close() logger.info("🏁 50-es batch feldolgozva.") if __name__ == "__main__": asyncio.run(TechEnricher.run())