Files
erp-nutzfahrzeuge/backend/app/models/sale.py
T

126 lines
3.7 KiB
Python
Raw Normal View History

"""SQLAlchemy model for sales (Verkauf)."""
import enum
import uuid
from datetime import date, datetime
from decimal import Decimal
from typing import TYPE_CHECKING
from sqlalchemy import (
Boolean,
CheckConstraint,
Date,
DateTime,
ForeignKey,
Numeric,
String,
func,
)
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.database import Base
if TYPE_CHECKING:
from app.models.contact import Contact
from app.models.vehicle import Vehicle
class SaleStatus(str, enum.Enum):
draft = "draft"
completed = "completed"
cancelled = "cancelled"
class Sale(Base):
"""Sale entity linking a vehicle to a buyer (and optionally a seller)."""
__tablename__ = "sales"
__table_args__ = (
CheckConstraint(
"status IN ('draft', 'completed', 'cancelled')",
name="ck_sales_status",
),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
vehicle_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("vehicles.id", ondelete="RESTRICT"),
nullable=False,
index=True,
)
buyer_contact_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("contacts.id", ondelete="RESTRICT"),
nullable=False,
index=True,
)
seller_contact_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("contacts.id", ondelete="SET NULL"),
nullable=True,
index=True,
)
sale_price: Mapped[Decimal] = mapped_column(
Numeric(12, 2), nullable=False
)
sale_date: Mapped[date] = mapped_column(
Date, nullable=False, default=func.current_date()
)
status: Mapped[str] = mapped_column(
String(20), nullable=False, default="draft"
)
is_gwg: Mapped[bool] = mapped_column(
Boolean, nullable=False, default=False
)
contract_pdf_path: Mapped[str | None] = mapped_column(
String(500), nullable=True
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, server_default=func.now()
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
server_default=func.now(),
onupdate=func.now(),
)
vehicle: Mapped["Vehicle"] = relationship(lazy="selectin")
buyer: Mapped["Contact"] = relationship(
"Contact",
foreign_keys=[buyer_contact_id],
lazy="selectin",
)
seller: Mapped["Contact | None"] = relationship(
"Contact",
foreign_keys=[seller_contact_id],
lazy="selectin",
)
def __repr__(self) -> str:
return f"<Sale id={self.id} vehicle_id={self.vehicle_id} status={self.status}>"
def to_dict(self) -> dict:
"""Serialize sale for API responses."""
return {
"id": str(self.id),
"vehicle_id": str(self.vehicle_id),
"buyer_contact_id": str(self.buyer_contact_id),
"seller_contact_id": (
str(self.seller_contact_id) if self.seller_contact_id else None
),
"sale_price": float(self.sale_price) if self.sale_price is not None else None,
"sale_date": self.sale_date.isoformat() if self.sale_date else None,
"status": self.status,
"is_gwg": self.is_gwg,
"contract_pdf_path": self.contract_pdf_path,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
}