# /opt/docker/dev/service_finder/backend/app/models/identity/social.py import enum import uuid from datetime import datetime from typing import Optional, List from sqlalchemy import String, Integer, ForeignKey, DateTime, Boolean, Text, UniqueConstraint, text from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.dialects.postgresql import ENUM as PG_ENUM, UUID as PG_UUID from sqlalchemy.sql import func from app.database import Base class ModerationStatus(str, enum.Enum): pending = "pending" approved = "approved" rejected = "rejected" class SourceType(str, enum.Enum): manual = "manual" ocr = "ocr" api_import = "import" class ServiceProvider(Base): """ Közösség által beküldött szolgáltatók (v1.3.1). """ __tablename__ = "service_providers" __table_args__ = {"schema": "marketplace"} id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True) name: Mapped[str] = mapped_column(String, nullable=False) address: Mapped[str] = mapped_column(String, nullable=False) category: Mapped[Optional[str]] = mapped_column(String) status: Mapped[ModerationStatus] = mapped_column( PG_ENUM(ModerationStatus, name="moderation_status", inherit_schema=True), default=ModerationStatus.pending ) source: Mapped[SourceType] = mapped_column( PG_ENUM(SourceType, name="source_type", inherit_schema=True), default=SourceType.manual ) validation_score: Mapped[int] = mapped_column(Integer, default=0) evidence_image_path: Mapped[Optional[str]] = mapped_column(String) added_by_user_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id")) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) class Vote(Base): """ Közösségi validációs szavazatok. """ __tablename__ = "votes" __table_args__ = ( UniqueConstraint('user_id', 'provider_id', name='uq_user_provider_vote'), {"schema": "marketplace"} ) id: Mapped[int] = mapped_column(Integer, primary_key=True) user_id: Mapped[int] = mapped_column(Integer, ForeignKey("identity.users.id"), nullable=False) provider_id: Mapped[int] = mapped_column(Integer, ForeignKey("marketplace.service_providers.id"), nullable=False) vote_value: Mapped[int] = mapped_column(Integer, nullable=False) # +1 vagy -1 class Competition(Base): """ Gamifikált versenyek (pl. Januári Feltöltő Verseny). """ __tablename__ = "competitions" __table_args__ = {"schema": "gamification"} id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str] = mapped_column(String, nullable=False) description: Mapped[Optional[str]] = mapped_column(Text) start_date: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False) end_date: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, default=True) class UserScore(Base): """ Versenyenkénti ranglista pontszámok. """ __tablename__ = "user_scores" __table_args__ = ( UniqueConstraint('user_id', 'competition_id', name='uq_user_competition_score'), {"schema": "gamification"} ) id: Mapped[int] = mapped_column(Integer, primary_key=True) user_id: Mapped[int] = mapped_column(Integer, ForeignKey("identity.users.id")) competition_id: Mapped[int] = mapped_column(Integer, ForeignKey("gamification.competitions.id")) points: Mapped[int] = mapped_column(Integer, default=0) last_updated: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) class ServiceReview(Base): """ Verifikált szerviz értékelések (Social 3). Csak igazolt pénzügyi tranzakció után lehet értékelni. """ __tablename__ = "service_reviews" __table_args__ = ( UniqueConstraint('transaction_id', name='uq_service_review_transaction'), {"schema": "marketplace"} ) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) service_id: Mapped[int] = mapped_column(Integer, ForeignKey("marketplace.service_profiles.id", ondelete="CASCADE"), nullable=False) user_id: Mapped[int] = mapped_column(Integer, ForeignKey("identity.users.id", ondelete="SET NULL"), nullable=False) transaction_id: Mapped[uuid.UUID] = mapped_column(PG_UUID(as_uuid=True), nullable=False, index=True) # Rating dimensions (1-10) price_rating: Mapped[int] = mapped_column(Integer, nullable=False) # 1-10 quality_rating: Mapped[int] = mapped_column(Integer, nullable=False) # 1-10 time_rating: Mapped[int] = mapped_column(Integer, nullable=False) # 1-10 communication_rating: Mapped[int] = mapped_column(Integer, nullable=False) # 1-10 comment: Mapped[Optional[str]] = mapped_column(Text) is_verified: Mapped[bool] = mapped_column(Boolean, default=True, server_default=text("true")) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), onupdate=func.now()) # Relationships service: Mapped["ServiceProfile"] = relationship("ServiceProfile", back_populates="reviews") user: Mapped["User"] = relationship("User", back_populates="service_reviews")