import enum from datetime import date, datetime from decimal import Decimal from sqlalchemy import Boolean, Date, DateTime, Enum, ForeignKey, Numeric, String, Text, func from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.base import Base class ServiceType(str, enum.Enum): maintenance = "maintenance" repair = "repair" fluid = "fluid" tire = "tire" inspection = "inspection" insurance = "insurance" tax = "tax" other = "other" class ExpenseCategory(str, enum.Enum): insurance = "insurance" tax = "tax" fine = "fine" parking = "parking" car_wash = "car_wash" toll = "toll" tires = "tires" wheels = "wheels" battery = "battery" parts = "parts" repair = "repair" maintenance = "maintenance" diagnostics = "diagnostics" towing = "towing" loan_payment = "loan_payment" loan_interest = "loan_interest" state_fee = "state_fee" registration = "registration" inspection = "inspection" other = "other" class FuelEntry(Base): __tablename__ = "fuel_entries" id: Mapped[int] = mapped_column(primary_key=True) car_id: Mapped[int] = mapped_column(ForeignKey("cars.id", ondelete="CASCADE"), index=True) entry_date: Mapped[date] = mapped_column(Date, index=True) odometer: Mapped[int] liters: Mapped[Decimal] = mapped_column(Numeric(8, 3)) price_per_liter: Mapped[Decimal] = mapped_column(Numeric(10, 2)) total_cost: Mapped[Decimal] = mapped_column(Numeric(12, 2)) station: Mapped[str | None] = mapped_column(String(160)) fuel_brand: Mapped[str | None] = mapped_column(String(80)) is_full_tank: Mapped[bool] = mapped_column(default=True) notes: Mapped[str | None] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) car = relationship("Car", back_populates="fuel_entries") class ServiceEntry(Base): __tablename__ = "service_entries" id: Mapped[int] = mapped_column(primary_key=True) car_id: Mapped[int] = mapped_column(ForeignKey("cars.id", ondelete="CASCADE"), index=True) entry_date: Mapped[date] = mapped_column(Date, index=True) odometer: Mapped[int | None] service_type: Mapped[ServiceType] = mapped_column(Enum(ServiceType), index=True) title: Mapped[str] = mapped_column(String(180)) category: Mapped[str | None] = mapped_column(String(80)) vendor: Mapped[str | None] = mapped_column(String(160)) total_cost: Mapped[Decimal] = mapped_column(Numeric(12, 2)) next_due_date: Mapped[date | None] = mapped_column(Date) next_due_odometer: Mapped[int | None] notes: Mapped[str | None] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) car = relationship("Car", back_populates="service_entries") class ExpenseEntry(Base): __tablename__ = "expense_entries" id: Mapped[int] = mapped_column(primary_key=True) car_id: Mapped[int] = mapped_column(ForeignKey("cars.id", ondelete="CASCADE"), index=True) entry_date: Mapped[date] = mapped_column(Date, index=True) category: Mapped[ExpenseCategory] = mapped_column(Enum(ExpenseCategory), index=True) title: Mapped[str] = mapped_column(String(180)) vendor: Mapped[str | None] = mapped_column(String(160)) total_cost: Mapped[Decimal] = mapped_column(Numeric(12, 2)) currency: Mapped[str] = mapped_column(String(3), default="RUB", server_default="RUB") odometer: Mapped[int | None] period_start: Mapped[date | None] = mapped_column(Date) period_end: Mapped[date | None] = mapped_column(Date) period_months: Mapped[int | None] is_recurring: Mapped[bool] = mapped_column(Boolean, default=False, server_default="false") notes: Mapped[str | None] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) car = relationship("Car", back_populates="expense_entries")