from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, distinct from app.models.asset import Asset, AssetCatalog, AssetTelemetry, AssetFinancials, AssetAssignment from app.models.gamification import UserStats, PointRule import logging logger = logging.getLogger(__name__) class AssetService: @staticmethod async def get_makes(db: AsyncSession): """1. Szint: Márkák lekérdezése (pl. Audi, BMW).""" stmt = select(distinct(AssetCatalog.make)).order_by(AssetCatalog.make) result = await db.execute(stmt) return result.scalars().all() @staticmethod async def get_models(db: AsyncSession, make: str): """2. Szint: Típusok szűrése márka alapján (pl. A4, A6).""" stmt = select(distinct(AssetCatalog.model)).where(AssetCatalog.make == make).order_by(AssetCatalog.model) result = await db.execute(stmt) return result.scalars().all() @staticmethod async def get_generations(db: AsyncSession, make: str, model: str): """3. Szint: Generációk/Évjáratok (pl. B8 (2008-2015)).""" stmt = select(distinct(AssetCatalog.generation)).where( AssetCatalog.make == make, AssetCatalog.model == model ).order_by(AssetCatalog.generation) result = await db.execute(stmt) return result.scalars().all() @staticmethod async def get_engines(db: AsyncSession, make: str, model: str, generation: str): """4. Szint: Motorváltozatok (pl. 2.0 TDI).""" stmt = select(AssetCatalog).where( AssetCatalog.make == make, AssetCatalog.model == model, AssetCatalog.generation == generation ).order_by(AssetCatalog.engine_variant) result = await db.execute(stmt) return result.scalars().all() @staticmethod async def create_and_assign_vehicle( db: AsyncSession, user_id: int, org_id: int, vin: str, license_plate: str, catalog_id: int = None ): """Jármű rögzítése, flottához rendelése és XP jóváírás (Atomic).""" try: # 1. Asset létrehozása közvetlen flotta-kötéssel new_asset = Asset( vin=vin, license_plate=license_plate, catalog_id=catalog_id, current_organization_id=org_id, # Izolációs pointer status="active", is_verified=False ) db.add(new_asset) await db.flush() # 2. Digitális Iker történetiség (Assignment) assignment = AssetAssignment( asset_id=new_asset.id, organization_id=org_id, status="active" ) db.add(assignment) # 3. Digitális Iker modulok indítása db.add(AssetTelemetry(asset_id=new_asset.id)) db.add(AssetFinancials(asset_id=new_asset.id)) # 4. GAMIFICATION: XP jóváírás rule_stmt = select(PointRule).where(PointRule.action_key == "ASSET_REGISTER") rule = (await db.execute(rule_stmt)).scalar_one_or_none() if rule: stats_stmt = select(UserStats).where(UserStats.user_id == user_id) stats = (await db.execute(stats_stmt)).scalar_one_or_none() if stats: stats.total_xp += rule.points logger.info(f"User {user_id} awarded {rule.points} XP for asset registration.") # 5. Robot Scout Trigger (későbbi implementáció) # await RobotScout.trigger_vin_lookup(db, new_asset.id) await db.commit() return new_asset except Exception as e: await db.rollback() logger.error(f"Asset Creation Error: {str(e)}") raise e