from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.db.session import get_db from app.schemas.asset import AssetCreate, AssetResponse from app.models.vehicle import Asset, VehicleCatalog from app.models.organization import Organization from app.core.validators import VINValidator from app.core.config import settings import os import logging router = APIRouter() logger = logging.getLogger(__name__) @router.post("/", response_model=AssetResponse, status_code=status.HTTP_201_CREATED) async def create_asset( asset_in: AssetCreate, db: AsyncSession = Depends(get_db) # Később ide jön: current_user: User = Depends(get_current_active_user) ): """ Új jármű (Asset) rögzítése a flottába. - Validálja a VIN-t (MOD 11 checksum). - Ellenőrzi a Katalógus elemet. - Létrehozza a NAS mappát a dokumentumoknak. """ # 1. VIN Validáció (Szigorú Checksum) # A GEM protokoll szerint kötelező a validátor használata is_valid_vin = VINValidator.validate(asset_in.vin) if not is_valid_vin: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Érvénytelen alvázszám (VIN)! A Checksum ellenőrzés sikertelen." ) # 2. Katalógus elem ellenőrzése stmt_catalog = select(VehicleCatalog).where(VehicleCatalog.id == asset_in.catalog_id) result_catalog = await db.execute(stmt_catalog) catalog_item = result_catalog.scalar_one_or_none() if not catalog_item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="A kiválasztott járműtípus nem található a katalógusban." ) # 3. Szervezet ellenőrzése (Létezik-e, és van-e joga - jogultságkezelés később) stmt_org = select(Organization).where(Organization.id == asset_in.organization_id) result_org = await db.execute(stmt_org) org_item = result_org.scalar_one_or_none() if not org_item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="A megadott flotta/szervezet nem található." ) # 4. Asset Duplikáció ellenőrzése (Ugyanaz a VIN nem szerepelhet 2x aktívként) # Megj: A UAI mező tárolja a VIN-t (Unique Asset Identifier) stmt_exist = select(Asset).where( Asset.uai == asset_in.vin.upper(), Asset.status != "deleted" ) result_exist = await db.execute(stmt_exist) if result_exist.scalar_one_or_none(): raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Ez a jármű (VIN) már szerepel a rendszerben!" ) # 5. Mentés az adatbázisba new_asset = Asset( uai=asset_in.vin.upper(), # A VIN a fő azonosító catalog_id=asset_in.catalog_id, organization_id=asset_in.organization_id, asset_type=catalog_item.category, # 'car', 'van', 'motorcycle', etc. name=asset_in.name or f"{catalog_item.brand} {catalog_item.model}", current_plate_number=asset_in.license_plate.upper(), status="active", privacy_level="private" # Alapértelmezett ) db.add(new_asset) await db.commit() await db.refresh(new_asset) # 6. NAS Tároló Létrehozása # Útvonal: /mnt/nas/app_data/assets/{uuid}/ # A settings.NAS_STORAGE_PATH-ot használjuk (GEM protokoll) try: # Ha a settings-ben nincs definiálva, fallback a hardcoded path-ra (biztonsági háló) base_path = getattr(settings, "NAS_STORAGE_PATH", "/mnt/nas/app_data/assets") asset_path = os.path.join(base_path, str(new_asset.id)) os.makedirs(asset_path, exist_ok=True) logger.info(f"NAS mappa létrehozva: {asset_path}") except OSError as e: logger.error(f"CRITICAL: Nem sikerült létrehozni a NAS mappát: {e}") # Nem dobunk hibát a usernek, mert az adatbázisba bekerült, de riasztunk logban return new_asset