40 lines
2.5 KiB
Python
Executable File
40 lines
2.5 KiB
Python
Executable File
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 app.schemas.fleet import EventCreate, TCOStats
|
|
from app.services.gamification_service import GamificationService
|
|
|
|
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"}
|
|
|
|
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}")
|
|
|
|
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
|
|
|
|
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)) |