Files
rentman-clone/backend/app/models/vehicle.py
T

96 lines
3.6 KiB
Python

"""Vehicle and VehicleAssignment models for fleet management."""
import uuid
from datetime import datetime
from sqlalchemy import String, DateTime, ForeignKey, func, Float, Text, Boolean
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.db.base import Base
class Vehicle(Base):
"""Represents a vehicle within a tenant account."""
__tablename__ = "vehicles"
id: Mapped[str] = mapped_column(
String(36), primary_key=True, default=lambda: str(uuid.uuid4())
)
account_id: Mapped[str] = mapped_column(
String(36), ForeignKey("accounts.id", ondelete="CASCADE"), nullable=False
)
name: Mapped[str] = mapped_column(String(255), nullable=False)
license_plate: Mapped[str | None] = mapped_column(
String(50), nullable=True, unique=True
)
brand: Mapped[str | None] = mapped_column(String(100), nullable=True)
model: Mapped[str | None] = mapped_column(String(100), nullable=True)
year: Mapped[int | None] = mapped_column(nullable=True)
color: Mapped[str | None] = mapped_column(String(50), nullable=True)
vehicle_type: Mapped[str | None] = mapped_column(String(50), nullable=True)
payload_capacity_kg: Mapped[float | None] = mapped_column(Float, nullable=True)
load_volume_m3: Mapped[float | None] = mapped_column(Float, nullable=True)
fuel_type: Mapped[str | None] = mapped_column(String(30), nullable=True)
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
notes: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
onupdate=func.now(),
nullable=False,
)
# Relationships
account: Mapped["Account"] = relationship("Account", back_populates="vehicles")
assignments: Mapped[list["VehicleAssignment"]] = relationship(
"VehicleAssignment", back_populates="vehicle", cascade="all, delete-orphan"
)
def __repr__(self) -> str:
return f"<Vehicle {self.name} ({self.license_plate or 'no plate'})>"
class VehicleAssignment(Base):
"""Tracks vehicle assignment to projects/events."""
__tablename__ = "vehicle_assignments"
id: Mapped[str] = mapped_column(
String(36), primary_key=True, default=lambda: str(uuid.uuid4())
)
vehicle_id: Mapped[str] = mapped_column(
String(36), ForeignKey("vehicles.id", ondelete="CASCADE"), nullable=False
)
project_id: Mapped[str | None] = mapped_column(String(36), nullable=True)
start_date: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False
)
end_date: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
status: Mapped[str] = mapped_column(
String(20), nullable=False, default="assigned"
) # assigned, in_use, returned
notes: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), nullable=False
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
onupdate=func.now(),
nullable=False,
)
# Relationships
vehicle: Mapped["Vehicle"] = relationship("Vehicle", back_populates="assignments")
def __repr__(self) -> str:
return (
f"<VehicleAssignment {self.vehicle_id}: {self.start_date}-{self.end_date}>"
)