Spaces:
Sleeping
Sleeping
| """ | |
| Assessment Model β ORM + Pydantic Schemas | |
| ORM: Assessment (SQLAlchemy table: assessments) | |
| Schemas: AssessmentCreate, AssessmentResponse | |
| Stores individual Ghost Shopper evaluation items for each visit. | |
| Each visit has ~21 assessment items grouped into 5 categories (AβE). | |
| Categories: | |
| A = Pelayanan Awal (Frontliner/Kasir) β 5 items | |
| B = Kualitas Produk (Minuman & Makanan) β 5 items | |
| C = Kebersihan dan Suasana Outlet β 4 items | |
| D = Kepatuhan SOP & Keselamatan β 2 items | |
| E = Keseluruhan Pengalaman Pelanggan β 5 items | |
| All ratings are normalized to a 1.0β5.0 float scale regardless of | |
| the original input format (Ya/Tidak, Qualitative, or Numeric). | |
| """ | |
| import uuid | |
| from datetime import datetime | |
| from typing import Optional | |
| from sqlalchemy import String, Text, Float, Integer, DateTime, ForeignKey, func | |
| from sqlalchemy.dialects.postgresql import UUID | |
| from sqlalchemy.orm import Mapped, mapped_column, relationship | |
| from pydantic import BaseModel, Field, ConfigDict | |
| from models.base import Base | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # ORM Model | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class Assessment(Base): | |
| """SQLAlchemy ORM model for the 'assessments' table.""" | |
| __tablename__ = "assessments" | |
| id: Mapped[uuid.UUID] = mapped_column( | |
| UUID(as_uuid=True), primary_key=True, default=uuid.uuid4 | |
| ) | |
| visit_id: Mapped[uuid.UUID] = mapped_column( | |
| UUID(as_uuid=True), | |
| ForeignKey("visits.id", ondelete="CASCADE"), | |
| nullable=False, | |
| ) | |
| category: Mapped[str] = mapped_column( | |
| String(1), nullable=False, | |
| comment="Assessment category: A, B, C, D, or E" | |
| ) | |
| item_no: Mapped[int] = mapped_column( | |
| Integer, nullable=False, | |
| comment="Item sequence number within the category (1-based)" | |
| ) | |
| criteria: Mapped[str] = mapped_column( | |
| String(500), nullable=False, | |
| comment="Assessment question/criteria text" | |
| ) | |
| score: Mapped[float] = mapped_column( | |
| Float, nullable=False, | |
| comment="Normalized score 1.0 to 5.0" | |
| ) | |
| raw_value: Mapped[str] = mapped_column( | |
| String(100), nullable=False, | |
| comment="Original value from document: 'Baik', 'Ya', '4', etc." | |
| ) | |
| notes: Mapped[Optional[str]] = mapped_column( | |
| Text, nullable=True, | |
| comment="Catatan / notes from the Ghost Shopper" | |
| ) | |
| description: Mapped[Optional[str]] = mapped_column( | |
| Text, nullable=True, | |
| comment="Detailed evaluator description / observation for this item" | |
| ) | |
| created_at: Mapped[datetime] = mapped_column( | |
| DateTime, server_default=func.now() | |
| ) | |
| # Relationships | |
| visit = relationship("Visit", back_populates="assessments") | |
| photos = relationship( | |
| "Photo", back_populates="assessment", | |
| cascade="all, delete-orphan", | |
| foreign_keys="Photo.assessment_id", | |
| ) | |
| def __repr__(self) -> str: | |
| return ( | |
| f"<Assessment(category={self.category}, item={self.item_no}, " | |
| f"score={self.score}, raw='{self.raw_value}')>" | |
| ) | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Pydantic Schemas | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class AssessmentCreate(BaseModel): | |
| """Schema for creating an assessment item.""" | |
| category: str = Field(..., min_length=1, max_length=1, description="Category A-E") | |
| item_no: int = Field(..., ge=1, le=10, description="Item number within category") | |
| criteria: str = Field(..., min_length=1, max_length=500, description="Criteria text") | |
| score: float = Field(..., ge=1.0, le=5.0, description="Normalized score 1.0-5.0") | |
| raw_value: str = Field(..., max_length=100, description="Original raw value") | |
| notes: Optional[str] = Field(None, description="Catatan from evaluator") | |
| description: Optional[str] = Field(None, description="Detailed observation/description for this item") | |
| class AssessmentResponse(BaseModel): | |
| """Schema for an assessment item in API responses.""" | |
| model_config = ConfigDict(from_attributes=True) | |
| id: uuid.UUID | |
| visit_id: uuid.UUID | |
| category: str | |
| item_no: int | |
| criteria: str | |
| score: float | |
| raw_value: str | |
| notes: Optional[str] | |
| description: Optional[str] | |
| created_at: datetime | |