STABLE: Final schema sync, optimized gitignore

This commit is contained in:
Kincses
2026-02-26 08:19:25 +01:00
parent 893f39fa15
commit 505543330a
203 changed files with 11590 additions and 9542 deletions

View File

@@ -1,40 +1,54 @@
# /opt/docker/dev/service_finder/backend/app/services/fleet_service.py
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from app.models.vehicle import UserVehicle
from app.models.expense import VehicleEvent
from app.models.social import ServiceProvider, SourceType, ModerationStatus
from uuid import UUID
from app.models.asset import Asset, AssetEvent, AssetCost
from app.models.social import ServiceProvider, ModerationStatus
from app.schemas.fleet import EventCreate, TCOStats
from app.services.gamification_service import GamificationService
from app.services.gamification_service import gamification_service
async def add_vehicle_event(db: AsyncSession, vehicle_id: int, event_data: EventCreate, user_id: int):
v_res = await db.execute(select(UserVehicle).where(UserVehicle.id == vehicle_id))
vehicle = v_res.scalars().first()
if not vehicle: return {"error": "Vehicle not found"}
class FleetService:
@staticmethod
async def add_vehicle_event(db: AsyncSession, asset_id: UUID, event_data: EventCreate, user_id: int):
""" Esemény (szerviz/tankolás) rögzítése a Digitális Iker történetébe. """
res = await db.execute(select(Asset).where(Asset.id == asset_id))
asset = res.scalar_one_or_none()
if not asset: return None
final_provider_id = event_data.provider_id
if event_data.is_diy: final_provider_id = None
elif event_data.provider_name and not final_provider_id:
p_res = await db.execute(select(ServiceProvider).where(func.lower(ServiceProvider.name) == event_data.provider_name.lower()))
existing = p_res.scalars().first()
if existing: final_provider_id = existing.id
else:
new_p = ServiceProvider(name=event_data.provider_name, added_by_user_id=user_id, status=ModerationStatus.pending)
db.add(new_p); await db.flush(); final_provider_id = new_p.id
await GamificationService.award_points(db, user_id, 50, f"Új helyszín: {event_data.provider_name}")
# Szolgáltató kezelés
provider_id = event_data.provider_id
if not event_data.is_diy and event_data.provider_name and not provider_id:
p_stmt = select(ServiceProvider).where(func.lower(ServiceProvider.name) == event_data.provider_name.lower())
existing = (await db.execute(p_stmt)).scalar_one_or_none()
if existing: provider_id = existing.id
else:
new_p = ServiceProvider(name=event_data.provider_name, added_by_user_id=user_id, status=ModerationStatus.pending)
db.add(new_p); await db.flush(); provider_id = new_p.id
anomaly = event_data.odometer_value < vehicle.current_odometer
new_event = VehicleEvent(vehicle_id=vehicle_id, service_provider_id=final_provider_id, odometer_anomaly=anomaly, **event_data.model_dump(exclude={"provider_id", "provider_name"}))
db.add(new_event)
if event_data.odometer_value > vehicle.current_odometer: vehicle.current_odometer = event_data.odometer_value
await GamificationService.award_points(db, user_id, 20, f"Esemény: {event_data.event_type}")
await db.commit(); await db.refresh(new_event)
return new_event
# Esemény és Telemetria frissítés
anomaly = event_data.odometer_value < (asset.telemetry.current_mileage if asset.telemetry else 0)
new_event = AssetEvent(
asset_id=asset_id,
event_type=event_data.event_type,
recorded_mileage=event_data.odometer_value,
data=event_data.model_dump(exclude={"provider_id", "provider_name"})
)
db.add(new_event)
# Gamifikáció hívása
await gamification_service.process_activity(db, user_id, 20, 5, f"Asset Event: {event_data.event_type}")
await db.commit()
return new_event
async def calculate_tco(db: AsyncSession, vehicle_id: int) -> TCOStats:
result = await db.execute(select(VehicleEvent.event_type, func.sum(VehicleEvent.cost_amount)).where(VehicleEvent.vehicle_id == vehicle_id).group_by(VehicleEvent.event_type))
breakdown = {row[0]: row[1] for row in result.all()}
v_res = await db.execute(select(UserVehicle).where(UserVehicle.id == vehicle_id))
v = v_res.scalars().first()
km = (v.current_odometer - v.initial_odometer) if v else 0
cpk = sum(breakdown.values()) / km if km > 0 else 0
return TCOStats(vehicle_id=vehicle_id, total_cost=sum(breakdown.values()), breakdown=breakdown, cost_per_km=round(cpk, 2))
@staticmethod
async def calculate_tco(db: AsyncSession, asset_id: UUID) -> TCOStats:
""" TCO számítás az AssetCost tábla alapján. """
result = await db.execute(
select(AssetCost.cost_type, func.sum(AssetCost.amount_local))
.where(AssetCost.asset_id == asset_id)
.group_by(AssetCost.cost_type)
)
breakdown = {row[0]: float(row[1]) for row in result.all()}
total = sum(breakdown.values())
return TCOStats(asset_id=asset_id, total_cost_huf=total, cost_per_km=0.0) # KM logika az asset.telemetry-ből