Files
service-finder/backend/app/api/v1/endpoints/assets.py

129 lines
4.5 KiB
Python

import uuid
from typing import Any, Dict, List
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from app.db.session import get_db
from app.api.deps import get_current_user
from app.models.asset import Asset, AssetCost, AssetTelemetry
from app.models.identity import User
from app.services.cost_service import cost_service
from app.schemas.asset_cost import AssetCostCreate, AssetCostResponse
router = APIRouter()
# --- 1. MODUL: IDENTITÁS (Alapadatok) ---
@router.get("/{asset_id}", response_model=Dict[str, Any])
async def get_asset_identity(
asset_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Csak a jármű alapadatai és katalógus információi."""
stmt = select(Asset).where(Asset.id == asset_id).options(selectinload(Asset.catalog))
asset = (await db.execute(stmt)).scalar_one_or_none()
if not asset:
raise HTTPException(status_code=404, detail="Jármű nem található")
return {
"id": asset.id,
"vin": asset.vin,
"license_plate": asset.license_plate,
"name": asset.name,
"catalog": {
"make": asset.catalog.make,
"model": asset.catalog.model,
"type": asset.catalog.vehicle_class,
"factory_data": getattr(asset.catalog, 'factory_data', {})
}
}
# --- 2. MODUL: PÉNZÜGY (Költségek) ---
@router.get("/{asset_id}/costs", response_model=Dict[str, Any])
async def get_asset_costs(
asset_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Pénzügyi modul: Helyi és EUR alapú összesítő, tételes lista."""
stmt = select(AssetCost).where(AssetCost.asset_id == asset_id)
costs = (await db.execute(stmt)).scalars().all()
summary_local = {}
summary_eur = {}
history = []
for c in costs:
cat = c.cost_type or "OTHER"
amt_local = float(c.amount_local)
amt_eur = float(c.amount_eur) if c.amount_eur else 0.0
summary_local[cat] = summary_local.get(cat, 0) + amt_local
summary_eur[cat] = summary_eur.get(cat, 0) + amt_eur
history.append({
"id": c.id,
"category": cat,
"amount_local": amt_local,
"currency_local": c.currency_local,
"amount_eur": amt_eur,
"exchange_rate": float(c.exchange_rate_used) if c.exchange_rate_used else 1.0,
"date": c.date
})
return {
"total_gross_local": sum(summary_local.values()),
"total_gross_eur": sum(summary_eur.values()),
"summary_local": summary_local,
"summary_eur": summary_eur,
"history": history
}
@router.post("/{asset_id}/costs", response_model=AssetCostResponse, status_code=status.HTTP_201_CREATED)
async def create_asset_cost(
asset_id: uuid.UUID,
cost_in: AssetCostCreate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""
Új költség rögzítése.
Automatikus: EUR konverzió, Telemetria frissítés, XP jóváírás.
"""
# Validáció: az asset_id-nak egyeznie kell a path-szal
if cost_in.asset_id != asset_id:
raise HTTPException(status_code=400, detail="Asset ID mismatch")
try:
new_cost = await cost_service.record_cost(
db=db,
cost_in=cost_in,
user_id=current_user.id
)
return new_cost
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# --- 3. MODUL: TELEMETRIA (Állapot) ---
@router.get("/{asset_id}/telemetry", response_model=Dict[str, Any])
async def get_asset_telemetry(
asset_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""Műszaki állapot: KM óra, VQI (Quality) és DBS (Driving) pontszámok."""
stmt = select(AssetTelemetry).where(AssetTelemetry.asset_id == asset_id)
tel = (await db.execute(stmt)).scalar_one_or_none()
if not tel:
return {"current_mileage": 0, "vqi_score": 100.0, "dbs_score": 100.0}
return {
"current_mileage": tel.current_mileage,
"vqi_score": float(tel.vqi_score),
"dbs_score": float(tel.dbs_score),
"last_update": tel.updated_at if hasattr(tel, 'updated_at') else None
}