Initial commit: Robot ökoszisztéma v2.0 - Stabilizált jármű és szerviz robotok
This commit is contained in:
153
backend/app/services/asset_service.py
Executable file
153
backend/app/services/asset_service.py
Executable file
@@ -0,0 +1,153 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/services/asset_service.py
|
||||
from __future__ import annotations
|
||||
import logging
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, func, and_
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from app.models.asset import Asset, AssetAssignment, AssetTelemetry, AssetFinancials
|
||||
from app.models.identity import User
|
||||
from app.services.config_service import config
|
||||
from app.services.gamification_service import GamificationService
|
||||
from app.services.security_service import security_service
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .identity import User, Person
|
||||
from .organization import Organization
|
||||
from .vehicle_definitions import VehicleModelDefinition
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class AssetService:
|
||||
"""
|
||||
Asset Service 2.0 - A Járművek Életciklus-menedzsere.
|
||||
Kezeli a regisztrációt, a tulajdonosváltást és a flotta-korlátokat.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
async def create_or_claim_vehicle(
|
||||
db: AsyncSession,
|
||||
user_id: int,
|
||||
org_id: int,
|
||||
vin: str,
|
||||
license_plate: str,
|
||||
catalog_id: int = None
|
||||
):
|
||||
"""
|
||||
Intelligens Jármű Rögzítés:
|
||||
Ha új: létrehozza.
|
||||
Ha már létezik: Transzfer folyamatot indít.
|
||||
"""
|
||||
try:
|
||||
vin_clean = vin.strip().upper()
|
||||
|
||||
# 1. ADMIN LIMIT ELLENŐRZÉS
|
||||
user_stmt = select(User).where(User.id == user_id)
|
||||
user = (await db.execute(user_stmt)).scalar_one()
|
||||
|
||||
limits = await config.get_setting(db, "VEHICLE_LIMIT", default={"free": 1, "premium": 5, "vip": 50})
|
||||
user_role = user.role.value if hasattr(user.role, 'value') else str(user.role)
|
||||
allowed_limit = limits.get(user_role, 1)
|
||||
|
||||
count_stmt = select(func.count(Asset.id)).where(Asset.current_organization_id == org_id)
|
||||
current_count = (await db.execute(count_stmt)).scalar()
|
||||
|
||||
if current_count >= allowed_limit:
|
||||
raise ValueError(f"Limit túllépés! A csomagod {allowed_limit} autót engedélyez.")
|
||||
|
||||
# 2. LÉTEZIK-E MÁR A JÁRMŰ?
|
||||
stmt = select(Asset).where(Asset.vin == vin_clean)
|
||||
existing_asset = (await db.execute(stmt)).scalar_one_or_none()
|
||||
|
||||
if existing_asset:
|
||||
# HA MÁR A JELENLEGI SZERVEZETNÉL VAN
|
||||
if existing_asset.current_organization_id == org_id:
|
||||
raise ValueError("Ez a jármű már a te garázsodban van.")
|
||||
|
||||
# TRANSZFER FOLYAMAT INDÍTÁSA
|
||||
return await AssetService.initiate_ownership_transfer(
|
||||
db, existing_asset, user_id, org_id, license_plate
|
||||
)
|
||||
|
||||
# 3. ÚJ JÁRMŰ LÉTREHOZÁSA (Standard Flow)
|
||||
new_asset = Asset(
|
||||
vin=vin_clean,
|
||||
license_plate=license_plate.strip().upper(),
|
||||
catalog_id=catalog_id,
|
||||
current_organization_id=org_id,
|
||||
status="active",
|
||||
is_verified=False
|
||||
)
|
||||
db.add(new_asset)
|
||||
await db.flush()
|
||||
|
||||
# Digitális Iker Alapmodulok
|
||||
db.add(AssetAssignment(asset_id=new_asset.id, organization_id=org_id, status="active"))
|
||||
db.add(AssetTelemetry(asset_id=new_asset.id))
|
||||
db.add(AssetFinancials(asset_id=new_asset.id))
|
||||
|
||||
# Gamification
|
||||
reward = await config.get_setting(db, "xp_reward_asset_register", default=250)
|
||||
await GamificationService.award_points(db, user_id, int(reward), "NEW_ASSET_REG")
|
||||
|
||||
await db.commit()
|
||||
return new_asset
|
||||
|
||||
except Exception as e:
|
||||
await db.rollback()
|
||||
logger.error(f"Asset Creation Error: {e}")
|
||||
raise e
|
||||
|
||||
@staticmethod
|
||||
async def initiate_ownership_transfer(db: AsyncSession, asset: Asset, user_id: int, org_id: int, new_plate: str):
|
||||
"""
|
||||
Adásvétel kezelése: Az autót 'Transfer Pending' állapotba teszi.
|
||||
"""
|
||||
# Admin paraméter: Automatikus transzfer engedélyezése?
|
||||
auto_transfer = await config.get_setting(db, "asset_auto_transfer_enabled", default=False)
|
||||
|
||||
# Logoljuk a kísérletet a biztonsági szolgálatnál (Sentinel)
|
||||
await security_service.log_event(
|
||||
db, user_id=user_id, action="VEHICLE_CLAIM_INITIATED",
|
||||
severity="warning", target_type="Asset", target_id=str(asset.id),
|
||||
new_data={"vin": asset.vin, "new_org": org_id}
|
||||
)
|
||||
|
||||
if auto_transfer:
|
||||
# Csak akkor, ha a régi tulajdonos 'sold' állapotba tette
|
||||
if asset.status == "sold":
|
||||
return await AssetService.execute_final_transfer(db, asset, org_id, new_plate)
|
||||
|
||||
# Függőben lévő állapot: Dokumentum feltöltésre vár
|
||||
asset.status = "transfer_pending"
|
||||
asset.temp_claim_org_id = org_id # Átmeneti tároló a validálásig
|
||||
|
||||
await db.commit()
|
||||
# Itt egy speciális hibaüzenetet dobunk, amit a Frontend tud kezelni (Dokumentum feltöltő ablak)
|
||||
raise HTTPException(
|
||||
status_code=202,
|
||||
detail="A jármű már szerepel a rendszerben. Kérjük, töltsd fel az adásvételi szerződést a tulajdonjog igazolásához."
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
async def execute_final_transfer(db: AsyncSession, asset: Asset, new_org_id: int, new_plate: str):
|
||||
""" A tulajdonjog tényleges átírása az adatbázisban. """
|
||||
# 1. Régi hozzárendelés lezárása
|
||||
await db.execute(
|
||||
update(AssetAssignment)
|
||||
.where(and_(AssetAssignment.asset_id == asset.id, AssetAssignment.status == "active"))
|
||||
.values(status="archived", end_date=datetime.now())
|
||||
)
|
||||
|
||||
# 2. Új hozzárendelés és adatok frissítése
|
||||
asset.current_organization_id = new_org_id
|
||||
asset.license_plate = new_plate.upper()
|
||||
asset.status = "active"
|
||||
asset.is_verified = False # Az új tulajdonos papírjait is ellenőrizni kell!
|
||||
|
||||
db.add(AssetAssignment(asset_id=asset.id, organization_id=new_org_id, status="active"))
|
||||
|
||||
await db.commit()
|
||||
return asset
|
||||
Reference in New Issue
Block a user