carcost/api/routers/vehicles.py
2026-04-10 23:24:51 +08:00

128 lines
4.0 KiB
Python

from fastapi import APIRouter, HTTPException
from typing import Optional
from decimal import Decimal
from database import get_session
from models import Vehicle, FuelRecord
from schemas import (
VehicleCreate,
VehicleUpdate,
VehicleDelete,
VehicleResponse,
VehicleStats,
)
router = APIRouter(prefix="/vehicles", tags=["vehicles"])
@router.get("/list", response_model=list[VehicleResponse])
def get_vehicles():
"""获取所有车辆列表(排除已删除)"""
with get_session() as session:
vehicles = (
session.query(Vehicle)
.filter(Vehicle.is_deleted == False)
.order_by(Vehicle.created_at.desc())
.all()
)
return vehicles
@router.post("/create", response_model=VehicleResponse)
def create_vehicle(vehicle: VehicleCreate):
"""添加新车辆"""
with get_session() as session:
db_vehicle = Vehicle(
name=vehicle.name,
purchase_date=vehicle.purchase_date,
initial_mileage=vehicle.initial_mileage,
)
session.add(db_vehicle)
session.commit()
session.refresh(db_vehicle)
return db_vehicle
@router.post("/update", response_model=VehicleResponse)
def update_vehicle(vehicle: VehicleUpdate):
"""更新车辆信息"""
with get_session() as session:
db_vehicle = session.query(Vehicle).filter(Vehicle.id == vehicle.id).first()
if not db_vehicle:
raise HTTPException(status_code=404, detail="Vehicle not found")
if vehicle.name is not None:
db_vehicle.name = vehicle.name
if vehicle.purchase_date is not None:
db_vehicle.purchase_date = vehicle.purchase_date
if vehicle.initial_mileage is not None:
db_vehicle.initial_mileage = vehicle.initial_mileage
session.commit()
session.refresh(db_vehicle)
return db_vehicle
@router.post("/delete")
def delete_vehicle(vehicle: VehicleDelete):
"""软删除车辆"""
with get_session() as session:
db_vehicle = (
session.query(Vehicle)
.filter(Vehicle.id == vehicle.id, Vehicle.is_deleted == False)
.first()
)
if not db_vehicle:
raise HTTPException(status_code=404, detail="Vehicle not found")
db_vehicle.is_deleted = True
session.commit()
return {"message": "Vehicle deleted successfully"}
@router.get("/stats", response_model=VehicleStats)
def get_vehicle_stats(vehicle_id: int):
"""获取车辆统计信息"""
with get_session() as session:
vehicle = (
session.query(Vehicle)
.filter(Vehicle.id == vehicle_id, Vehicle.is_deleted == False)
.first()
)
if not vehicle:
raise HTTPException(status_code=404, detail="Vehicle not found")
# 获取所有未删除的加油记录
fuel_records = (
session.query(FuelRecord)
.filter(FuelRecord.vehicle_id == vehicle_id, FuelRecord.is_deleted == False)
.order_by(FuelRecord.date.asc())
.all()
)
# 计算总里程
if fuel_records:
latest_mileage = max(r.mileage for r in fuel_records)
total_mileage = latest_mileage - vehicle.initial_mileage
else:
total_mileage = 0
# 计算总油费和总加油量(只算加满的记录)
total_fuel_cost = sum(float(r.total_cost) for r in fuel_records)
total_fuel_amount = sum(
float(r.fuel_amount) for r in fuel_records if r.is_full_tank
)
# 计算平均油耗
avg_fuel_consumption = None
if total_mileage > 0 and total_fuel_amount > 0:
avg_fuel_consumption = round((total_fuel_amount / total_mileage) * 100, 2)
return VehicleStats(
total_mileage=total_mileage,
total_fuel_cost=round(total_fuel_cost, 2),
total_fuel_amount=round(total_fuel_amount, 2),
avg_fuel_consumption=avg_fuel_consumption,
)