# /opt/docker/dev/service_finder/backend/app/models/system/system.py import uuid from datetime import datetime, date from enum import Enum from typing import Optional from sqlalchemy import String, Integer, Boolean, DateTime, text, UniqueConstraint, ForeignKey, Text, Enum as SQLEnum, Date from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.dialects.postgresql import JSONB, UUID from sqlalchemy.sql import func from app.database import Base class ParameterScope(str, Enum): GLOBAL = "global" COUNTRY = "country" REGION = "region" ORGANIZATION = "organization" USER = "user" class SystemParameter(Base): """ Dinamikus konfigurációs motor (Global -> Org -> User). """ __tablename__ = "system_parameters" __table_args__ = ( UniqueConstraint('key', 'scope_level', 'scope_id', name='uix_param_scope'), {"schema": "system", "extend_existing": True} ) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) key: Mapped[str] = mapped_column(String, index=True) category: Mapped[str] = mapped_column(String, server_default="general", index=True) value: Mapped[dict] = mapped_column(JSONB, nullable=False) scope_level: Mapped[ParameterScope] = mapped_column(SQLEnum(ParameterScope, name="parameter_scope", schema="system"), server_default=ParameterScope.GLOBAL.value, index=True) scope_id: Mapped[Optional[str]] = mapped_column(String(50)) is_active: Mapped[bool] = mapped_column(Boolean, default=True) description: Mapped[Optional[str]] = mapped_column(String) last_modified_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), onupdate=func.now(), server_default=func.now()) class InternalNotification(Base): """ Belső értesítési központ. Ezek az üzenetek várják a felhasználót belépéskor. """ __tablename__ = "internal_notifications" __table_args__ = ({"schema": "system", "extend_existing": True}) id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id: Mapped[int] = mapped_column(ForeignKey("identity.users.id", ondelete="CASCADE"), nullable=False, index=True) title: Mapped[str] = mapped_column(String(255), nullable=False) message: Mapped[str] = mapped_column(Text, nullable=False) category: Mapped[str] = mapped_column(String(50), server_default="info") priority: Mapped[str] = mapped_column(String(20), server_default="medium") is_read: Mapped[bool] = mapped_column(Boolean, default=False, index=True) read_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) data: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True) class SystemDataCompletionWeight(Base): """Adatkitöltési súlyok rendszerszintű konfigurációja - mely mezők mennyire fontosak a profil teljességéhez.""" __tablename__ = "system_data_completion_weights" __table_args__ = ( UniqueConstraint('entity_type', 'field_name', name='uix_entity_field'), {"schema": "system"} ) id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) entity_type: Mapped[str] = mapped_column(String(50), nullable=False, index=True) # pl: "vehicle", "person", "organization" field_name: Mapped[str] = mapped_column(String(100), nullable=False, index=True) # pl: "vin", "license_plate", "email" weight_percent: Mapped[int] = mapped_column(Integer, nullable=False) # 0-100% is_mandatory: Mapped[bool] = mapped_column(Boolean, default=False) is_active: Mapped[bool] = mapped_column(Boolean, default=True) description: Mapped[Optional[str]] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) # Shadow column that exists in database (should be removed in future migration) is_read: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) class SystemServiceStaging(Base): """ Robot 1.3 (Scout) által talált nyers szerviz adatok. """ __tablename__ = "service_staging" __table_args__ = {"schema": "system"} id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str] = mapped_column(String(255), index=True) source: Mapped[str] = mapped_column(String(50)) external_id: Mapped[Optional[str]] = mapped_column(String(100), index=True) fingerprint: Mapped[str] = mapped_column(String(64), unique=True, index=True) postal_code: Mapped[Optional[str]] = mapped_column(String(20), index=True) city: Mapped[str] = mapped_column(String(100), index=True) full_address: Mapped[Optional[str]] = mapped_column(String(500)) contact_phone: Mapped[Optional[str]] = mapped_column(String(50)) website: Mapped[Optional[str]] = mapped_column(String(255)) contact_email: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) raw_data: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb")) status: Mapped[str] = mapped_column(String(20), default="pending", index=True) trust_score: Mapped[int] = mapped_column(Integer, default=30) 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()) # JAVÍTÁS: Ezeket az oszlopokat vissza kell tenni, mert az audit szerint # az adatbázisban léteznek a system.service_staging táblában. read_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True) data: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True)