feat(infra): Stabilized Docker env, fixed circular imports, enabled AI Enricher Robot v1.1

This commit is contained in:
2026-02-17 01:26:18 +00:00
parent d574d3297d
commit 2def6b2201
34 changed files with 1559 additions and 112 deletions

View File

@@ -0,0 +1,78 @@
import asyncio
from sqlalchemy import select, update, func
from app.db.session import SessionLocal
from app.models.asset import AssetCatalog
from app.models.vehicle_definitions import VehicleModelDefinition, VehicleType
async def link_catalog_to_mdm():
async with SessionLocal() as db:
try:
print("🔍 Meglévő variánsok elemzése...")
# 1. Lekérjük a típusokat a gyors kereséshez
type_res = await db.execute(select(VehicleType))
types = {t.code: t.id for t in type_res.scalars().all()}
# 2. Kigyűjtjük az egyedi márkákat és modelleket a katalógusból
# Itt csoportosítunk, hogy ne legyen duplikáció
stmt = select(
AssetCatalog.make,
AssetCatalog.model,
AssetCatalog.vehicle_class
).distinct()
raw_data = await db.execute(stmt)
unique_models = raw_data.all()
print(f"📊 Találtunk {len(unique_models)} egyedi modellt. Összefésülés indul...")
linked_count = 0
for make, model, v_class in unique_models:
# Meghatározzuk a típus ID-t (alapértelmezett: car)
t_code = v_class if v_class in types else "car"
t_id = types.get(t_code)
# Keressük, létezik-e már ilyen Master rekord
# A technical_code-ot itt ideiglenesen a modell nevével töltjük,
# amíg a robot/AI nem pontosítja
master_stmt = select(VehicleModelDefinition).where(
VehicleModelDefinition.make == make,
VehicleModelDefinition.marketing_name == model
)
master_res = await db.execute(master_stmt)
master = master_res.scalar_one_or_none()
if not master:
master = VehicleModelDefinition(
make=make,
technical_code=model, # Ideiglenes
marketing_name=model,
vehicle_type=t_code,
vehicle_type_id=t_id,
status="unverified",
source="initial_linking"
)
db.add(master)
await db.flush() # Hogy megkapjuk az ID-t
# 3. Összekötjük az összes variánst ezzel a Master rekorddal
update_stmt = update(AssetCatalog).where(
AssetCatalog.make == make,
AssetCatalog.model == model
).values(master_definition_id=master.id)
await db.execute(update_stmt)
linked_count += 1
if linked_count % 100 == 0:
print(f"⏳ Feldolgozva: {linked_count} modell...")
await db.commit()
print(f"✅ Kész! {linked_count} Master rekord létrehozva és összekötve.")
except Exception as e:
await db.rollback()
print(f"❌ Hiba az összefésülésnél: {e}")
if __name__ == "__main__":
asyncio.run(link_catalog_to_mdm())

View File

@@ -0,0 +1,42 @@
import asyncio
from sqlalchemy import select, func
from app.db.session import SessionLocal
from app.models.audit import ProcessLog
from datetime import datetime, timedelta
async def generate_morning_report():
async with SessionLocal() as db:
# Az elmúlt 24 óra logjai
yesterday = datetime.now() - timedelta(days=1)
stmt = select(ProcessLog).where(ProcessLog.start_time >= yesterday)
res = await db.execute(stmt)
logs = res.scalars().all()
report = f"📊 REGGELI ROBOT JELENTÉS - {datetime.now().date()}\n"
report += "="*40 + "\n"
total_proc = 0
total_fail = 0
cleaned_list = []
for log in logs:
total_proc += log.items_processed
total_fail += log.items_failed
if "cleaned" in log.details:
cleaned_list.extend(log.details["cleaned"])
report += f"✅ Feldolgozott modellek: {total_proc}\n"
report += f"❌ Hibás/Sikertelen: {total_fail}\n"
report += f"🧹 AI névtisztítások száma: {len(cleaned_list)}\n\n"
if cleaned_list:
report += "Példák a tisztított nevekre:\n"
for item in cleaned_list[:10]: # Csak az első 10-et listázzuk
report += f" - {item}\n"
print(report)
# Itt hívható az EmailManager.send(...)
return report
if __name__ == "__main__":
asyncio.run(generate_morning_report())

View File

@@ -2,7 +2,7 @@ import asyncio
import json
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from app.models.system_config import SystemParameter
from app.models import SystemParameter
from app.core.config import settings
async def seed_system():

View File

@@ -0,0 +1,84 @@
import asyncio
from sqlalchemy import select
from sqlalchemy.orm import configure_mappers
from app.db.session import SessionLocal
# Fontos: Importálunk minden modellt a regisztrációhoz
import app.models
from app.models.vehicle_definitions import VehicleType, FeatureDefinition
async def seed_system_data():
# Kényszerített mapper konfiguráció a hiba ellen
try:
configure_mappers()
except Exception as e:
print(f"⚠️ Mapper figyelmeztetés (lehet, hogy már kész): {e}")
async with SessionLocal() as db:
try:
print("🚀 Kezdődik a rendszeradatok beoltása...")
# 1. Jármű Fajták (Blueprints)
types_data = [
{"code": "car", "name": "Személyautó", "icon": "directions_car"},
{"code": "motorcycle", "name": "Motorkerékpár", "icon": "moped"},
{"code": "truck", "name": "Teherautó/Kamion", "icon": "local_shipping"},
{"code": "bus", "name": "Autóbusz", "icon": "directions_bus"},
{"code": "boat", "name": "Hajó/Vitorlás", "icon": "sailing"},
{"code": "camper", "name": "Lakóautó", "icon": "rv_hookup"},
{"code": "machinery", "name": "Munkagép", "icon": "construction"},
{"code": "trailer", "name": "Utánfutó", "icon": "trailer"}
]
type_id_map = {}
for t_info in types_data:
stmt = select(VehicleType).where(VehicleType.code == t_info["code"])
res = await db.execute(stmt)
v_type = res.scalar_one_or_none()
if not v_type:
v_type = VehicleType(**t_info)
db.add(v_type)
await db.flush()
type_id_map[t_info["code"]] = v_type.id
# 2. Extrák (Features) betöltése - A te listád alapján
features = {
"car": [
("Műszaki", "ABS (blokkolásgátló)"), ("Műszaki", "ESP (menetstabilizátor)"),
("Műszaki", "távolságtartó tempomat"), ("Beltér", "ISOFIX rendszer"),
("Multimédia", "Android Auto"), ("Multimédia", "Apple CarPlay")
],
"truck": [
("Munkavégzés", "elektromos retarder"), ("Munkavégzés", "intarder"),
("Munkavégzés", "AdBlue"), ("Fülke", "hálófülke")
],
"boat": [
("Műszaki", "orrsugárkormány"), ("Műszaki", "halradar"),
("Műszaki", "elektromos horgonycsörlő")
]
}
for code, items in features.items():
t_id = type_id_map.get(code)
if not t_id: continue
for cat, name in items:
stmt = select(FeatureDefinition).where(
FeatureDefinition.name == name,
FeatureDefinition.vehicle_type_id == t_id
)
res = await db.execute(stmt)
if not res.scalar_one_or_none():
db.add(FeatureDefinition(
vehicle_type_id=t_id, category=cat, name=name, data_type="boolean"
))
await db.commit()
print("✅ Minden alapadat (Types & Features) sikeresen betöltve!")
except Exception as e:
await db.rollback()
print(f"❌ Végzetes hiba a feltöltés során: {e}")
raise e
if __name__ == "__main__":
asyncio.run(seed_system_data())