2026-07-17 09:31:28 +02:00
|
|
|
"""SQLAlchemy model for image retouch results."""
|
|
|
|
|
|
|
|
|
|
import enum
|
|
|
|
|
import uuid
|
|
|
|
|
from datetime import datetime
|
2026-07-17 21:16:38 +02:00
|
|
|
from typing import TYPE_CHECKING
|
2026-07-17 09:31:28 +02:00
|
|
|
|
|
|
|
|
from sqlalchemy import DateTime, ForeignKey, String, Text, func
|
|
|
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
|
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
|
|
|
|
|
|
from app.database import Base
|
|
|
|
|
|
2026-07-17 21:16:38 +02:00
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
from app.models.vehicle import Vehicle
|
|
|
|
|
|
2026-07-17 09:31:28 +02:00
|
|
|
|
|
|
|
|
class RetouchStatus(str, enum.Enum):
|
|
|
|
|
pending = "pending"
|
|
|
|
|
processing = "processing"
|
|
|
|
|
completed = "completed"
|
|
|
|
|
failed = "failed"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RetouchResult(Base):
|
|
|
|
|
"""Retouch result entity tracking image retouching via Flux.1-Pro."""
|
|
|
|
|
|
|
|
|
|
__tablename__ = "retouch_results"
|
|
|
|
|
|
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
|
|
|
UUID(as_uuid=True),
|
|
|
|
|
primary_key=True,
|
|
|
|
|
default=uuid.uuid4,
|
|
|
|
|
)
|
|
|
|
|
vehicle_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
|
|
|
UUID(as_uuid=True),
|
|
|
|
|
ForeignKey("vehicles.id", ondelete="SET NULL"),
|
|
|
|
|
nullable=True,
|
|
|
|
|
index=True,
|
|
|
|
|
)
|
|
|
|
|
original_file_path: Mapped[str] = mapped_column(
|
|
|
|
|
String(512), nullable=False
|
|
|
|
|
)
|
|
|
|
|
original_file_name: Mapped[str] = mapped_column(
|
|
|
|
|
String(255), nullable=False
|
|
|
|
|
)
|
|
|
|
|
mime_type: Mapped[str] = mapped_column(
|
|
|
|
|
String(100), nullable=False, default="image/png"
|
|
|
|
|
)
|
|
|
|
|
retouched_file_path: Mapped[str | None] = mapped_column(
|
|
|
|
|
String(512), nullable=True
|
|
|
|
|
)
|
|
|
|
|
status: Mapped[str] = mapped_column(
|
|
|
|
|
String(20), nullable=False, default="pending"
|
|
|
|
|
)
|
|
|
|
|
error_message: Mapped[str | None] = mapped_column(
|
|
|
|
|
Text, 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("Vehicle")
|
|
|
|
|
|
|
|
|
|
def __repr__(self) -> str:
|
|
|
|
|
return f"<RetouchResult id={self.id} status={self.status}>"
|
|
|
|
|
|
|
|
|
|
def to_dict(self) -> dict:
|
|
|
|
|
"""Serialize retouch result for API responses."""
|
|
|
|
|
return {
|
|
|
|
|
"id": str(self.id),
|
|
|
|
|
"vehicle_id": str(self.vehicle_id) if self.vehicle_id else None,
|
|
|
|
|
"original_file_path": self.original_file_path,
|
|
|
|
|
"original_file_name": self.original_file_name,
|
|
|
|
|
"mime_type": self.mime_type,
|
|
|
|
|
"retouched_file_path": self.retouched_file_path,
|
|
|
|
|
"status": self.status,
|
|
|
|
|
"error_message": self.error_message,
|
|
|
|
|
"created_at": (
|
|
|
|
|
self.created_at.isoformat() if self.created_at else None
|
|
|
|
|
),
|
|
|
|
|
"updated_at": (
|
|
|
|
|
self.updated_at.isoformat() if self.updated_at else None
|
|
|
|
|
),
|
|
|
|
|
}
|