Initial commit: Robot ökoszisztéma v2.0 - Stabilizált jármű és szerviz robotok

This commit is contained in:
Kincses
2026-03-04 02:03:03 +01:00
commit 250f4f4b8f
7942 changed files with 449625 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, desc
from app.models.vehicle import Vehicle
from app.models.expense import VehicleEvent, ExpenseCategory
from app.models.social import ServiceProvider, SourceType, ModerationStatus
from app.schemas.fleet import EventCreate, TCOStats
async def add_vehicle_event(db: AsyncSession, vehicle_id: int, event_data: EventCreate, user_id: int):
"""
Összetett logika esemény rögzítésére:
1. Provider kezelés (DIY vs Existing vs New Ad-Hoc)
2. Odometer integritás ellenőrzés
3. Mentés és Jármű frissítés
"""
# 1. Jármű ellenőrzése
vehicle_res = await db.execute(select(Vehicle).where(Vehicle.id == vehicle_id))
vehicle = vehicle_res.scalars().first()
if not vehicle:
return {"error": "Vehicle not found"}
# 2. Provider Logika
final_provider_id = event_data.provider_id
if event_data.is_diy:
# Ha DIY, akkor nincs provider
final_provider_id = None
if not event_data.description:
event_data.description = "Saját javítás (DIY)"
elif event_data.provider_name and not final_provider_id:
# Ha nevet kaptunk, de ID-t nem -> Keresés vagy Létrehozás
# Megpróbáljuk megkeresni név alapján (case insensitive)
provider_res = await db.execute(select(ServiceProvider).where(func.lower(ServiceProvider.name) == event_data.provider_name.lower()))
existing_provider = provider_res.scalars().first()
if existing_provider:
final_provider_id = existing_provider.id
else:
# Nem létezik -> Létrehozunk egy "Fantom" szolgáltatót
new_provider = ServiceProvider(
name=event_data.provider_name,
address="Unknown (User Generated)",
status=ModerationStatus.pending, # Ellenőrzésre vár
source=SourceType.manual,
added_by_user_id=user_id
)
db.add(new_provider)
await db.flush() # Hogy kapjunk ID-t
final_provider_id = new_provider.id
print(f"--- INFO: Created Ad-Hoc Provider: {event_data.provider_name} (ID: {final_provider_id})")
# 3. Odometer Logika (Biztonság)
anomaly_detected = False
if event_data.odometer_value < vehicle.current_odometer:
# Figyelmeztetés: Csökkent a kilométerállás!
anomaly_detected = True
print(f"--- WARN: Odometer rollback detected for Vehicle {vehicle_id}!")
# 4. Esemény mentése
new_event = VehicleEvent(
vehicle_id=vehicle_id,
event_type=event_data.event_type,
date=event_data.date,
odometer_value=event_data.odometer_value,
odometer_anomaly=anomaly_detected,
cost_amount=event_data.cost_amount,
description=event_data.description,
is_diy=event_data.is_diy,
service_provider_id=final_provider_id
)
db.add(new_event)
# 5. Jármű frissítése (Ha nőtt a km, update-eljük a current-et)
if event_data.odometer_value > vehicle.current_odometer:
vehicle.current_odometer = event_data.odometer_value
await db.commit()
await db.refresh(new_event)
return new_event
async def calculate_tco(db: AsyncSession, vehicle_id: int) -> TCOStats:
"""Teljes költség elemzés (TCO)"""
# Költségek lekérése kategóriánként
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()}
total_cost = sum(breakdown.values())
# Km futás számítás
vehicle_res = await db.execute(select(Vehicle).where(Vehicle.id == vehicle_id))
vehicle = vehicle_res.scalars().first()
km_driven = 0
cost_per_km = 0.0
if vehicle:
km_driven = max(0, vehicle.current_odometer - vehicle.initial_odometer)
if km_driven > 0:
cost_per_km = total_cost / km_driven
return TCOStats(
vehicle_id=vehicle_id,
total_cost=total_cost,
breakdown=breakdown,
cost_per_km=round(cost_per_km, 2)
)