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

129 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fastapi import APIRouter, HTTPException
from typing import Optional
from database import get_session
from models import Vehicle, FuelRecord
from schemas import DashboardData, FuelRecordItem
router = APIRouter(prefix="/dashboard", tags=["dashboard"])
@router.get("/data", response_model=DashboardData)
def get_dashboard(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)
# 获取最近5条加油记录带油耗计算排除已删除
recent_records = (
session.query(FuelRecord)
.filter(FuelRecord.vehicle_id == vehicle_id, FuelRecord.is_deleted == False)
.order_by(FuelRecord.date.desc(), FuelRecord.mileage.desc())
.limit(5)
.all()
)
recent_fuel_records = []
for record in recent_records:
# 计算单次油耗
fuel_consumption = None
if record.is_full_tank:
# 先找更早日期的记录
prev_record = (
session.query(FuelRecord)
.filter(
FuelRecord.vehicle_id == vehicle_id,
FuelRecord.date < record.date,
FuelRecord.is_full_tank == True,
FuelRecord.is_deleted == False,
)
.order_by(FuelRecord.date.desc(), FuelRecord.mileage.desc())
.first()
)
# 如果没找到,找同一天更早的记录
if not prev_record:
prev_record = (
session.query(FuelRecord)
.filter(
FuelRecord.vehicle_id == vehicle_id,
FuelRecord.date == record.date,
FuelRecord.mileage < record.mileage,
FuelRecord.is_full_tank == True,
FuelRecord.is_deleted == False,
)
.order_by(FuelRecord.mileage.desc())
.first()
)
if prev_record:
mileage_diff = record.mileage - prev_record.mileage
if mileage_diff > 0:
fuel_consumption = round(
(float(record.fuel_amount) / mileage_diff) * 100, 2
)
recent_fuel_records.append(
FuelRecordItem(
id=record.id,
date=record.date,
mileage=record.mileage,
fuel_amount=float(record.fuel_amount),
total_cost=float(record.total_cost),
fuel_consumption=fuel_consumption,
)
)
# 计算日均行程
avg_daily_km = None
if total_mileage > 0 and fuel_records:
first_date = fuel_records[0].date # 第一次加油日期(已按日期升序排序)
last_date = fuel_records[-1].date # 最后一次加油日期
days = (last_date - first_date).days
if days > 0:
avg_daily_km = round(total_mileage / days, 1)
return DashboardData(
vehicle_id=vehicle_id,
vehicle_name=vehicle.name,
purchase_date=vehicle.purchase_date,
total_mileage=total_mileage,
total_fuel_cost=round(total_fuel_cost, 2),
avg_fuel_consumption=avg_fuel_consumption,
avg_daily_km=avg_daily_km,
recent_fuel_records=recent_fuel_records,
)