STABLE: Final schema sync, optimized gitignore
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user