Files
drivers_bot/app/models/expense.py
2026-05-14 21:19:37 +09:00

109 lines
4.3 KiB
Python

import enum
from datetime import date, datetime
from decimal import Decimal
from sqlalchemy import JSON, 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 | None] = mapped_column(Boolean, nullable=True, default=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="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")
policy_number: Mapped[str | None] = mapped_column(String(120))
insurance_type: Mapped[str | None] = mapped_column(String(40))
payment_period_months: Mapped[int | None] = mapped_column()
document_urls: Mapped[list | None] = mapped_column(JSON)
metadata_json: Mapped[dict | None] = mapped_column(JSON)
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")