feat: Asset Catalog system, PostGIS integration and RobotScout V1
This commit is contained in:
@@ -1,35 +1,99 @@
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
from app.models.asset import Asset, AssetTelemetry, AssetFinancials
|
||||
from sqlalchemy import select, distinct
|
||||
from app.models.asset import Asset, AssetCatalog, AssetTelemetry, AssetFinancials, AssetAssignment
|
||||
from app.models.gamification import UserStats, PointRule
|
||||
import uuid
|
||||
import logging
|
||||
|
||||
async def create_new_vehicle(db: AsyncSession, user_id: int, vin: str, license_plate: str):
|
||||
# 1. Alap Asset létrehozása
|
||||
new_asset = Asset(
|
||||
vin=vin,
|
||||
license_plate=license_plate,
|
||||
name=f"Teszt Autó ({license_plate})"
|
||||
)
|
||||
db.add(new_asset)
|
||||
await db.flush() # Hogy legyen ID-ja
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 2. Modulok inicializálása (Digital Twin alapozás)
|
||||
db.add(AssetTelemetry(asset_id=new_asset.id, current_mileage=0))
|
||||
db.add(AssetFinancials(asset_id=new_asset.id))
|
||||
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()
|
||||
|
||||
# 3. GAMIFICATION: Pontszerzés (ASSET_REGISTER = 100 XP)
|
||||
# Megkeressük a szabályt
|
||||
rule_stmt = select(PointRule).where(PointRule.action_key == "ASSET_REGISTER")
|
||||
rule = (await db.execute(rule_stmt)).scalar_one_or_none()
|
||||
|
||||
if rule:
|
||||
# Frissítjük a felhasználó XP-jét
|
||||
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
|
||||
# Itt később jöhet a szintlépés ellenőrzése is!
|
||||
@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()
|
||||
|
||||
await db.commit()
|
||||
return new_asset
|
||||
@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
|
||||
Reference in New Issue
Block a user