import uuid from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, JSON, text, Text, Float from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import UUID as PG_UUID, JSONB from geoalchemy2 import Geometry # PostGIS támogatás from sqlalchemy.sql import func from app.db.base_class import Base class ServiceProfile(Base): """ Szerviz szolgáltató kiterjesztett adatai. Egy Organization-höz (org_type='service') kapcsolódik. """ __tablename__ = "service_profiles" __table_args__ = {"schema": "data"} id = Column(Integer, primary_key=True, index=True) organization_id = Column(Integer, ForeignKey("data.organizations.id"), unique=True) # PostGIS GPS pont (SRID 4326 = WGS84 koordináták) location = Column(Geometry(geometry_type='POINT', srid=4326), index=True) # Állapotkezelés: ghost, active, flagged, inactive status = Column(String(20), server_default=text("'ghost'"), index=True) last_audit_at = Column(DateTime(timezone=True), server_default=func.now()) # --- MAGÁNNYOMOZÓ (Deep Enrichment) ADATOK --- google_place_id = Column(String(100), unique=True) rating = Column(Float) user_ratings_total = Column(Integer) # Bentley vs BMW logika: JSONB a gyors, márkaszintű szűréshez # Példa: {"brands": ["Bentley", "Audi"], "specialty": ["engine", "tuning"]} specialization_tags = Column(JSONB, server_default=text("'{}'::jsonb")) # Trust Engine (Bot Discovery=30, User Entry=50, Admin/Partner=100) trust_score = Column(Integer, default=30) is_verified = Column(Boolean, default=False) verification_log = Column(JSON, server_default=text("'{}'::jsonb")) opening_hours = Column(JSON, server_default=text("'{}'::jsonb")) contact_phone = Column(String) website = Column(String) bio = Column(Text) # Kapcsolatok organization = relationship("Organization") expertises = relationship("ServiceExpertise", back_populates="service") class ExpertiseTag(Base): """Szakmai szempontok taxonómiája.""" __tablename__ = "expertise_tags" __table_args__ = {"schema": "data"} id = Column(Integer, primary_key=True) key = Column(String(50), unique=True, index=True) # pl. 'bmw_gs_specialist' name_hu = Column(String(100)) category = Column(String(30)) # 'repair', 'fuel', 'food', 'emergency' class ServiceExpertise(Base): """Kapcsolótábla a szerviz és a szakterület között.""" __tablename__ = "service_expertises" __table_args__ = {"schema": "data"} service_id = Column(Integer, ForeignKey("data.service_profiles.id"), primary_key=True) expertise_id = Column(Integer, ForeignKey("data.expertise_tags.id"), primary_key=True) # Validációs szint (0-100% - Mennyire hiteles ez a szakértelem) validation_level = Column(Integer, default=0) service = relationship("ServiceProfile", back_populates="expertises") expertise = relationship("ExpertiseTag") class ServiceStaging(Base): """ Átmeneti tábla a Hunter (n8n/scraping) adatoknak. A címek itt már darabolva (IRSZ, Város, Utca, Házszám) szerepelnek a jobb kereshetőség és validálás érdekében. """ __tablename__ = "service_staging" __table_args__ = {"schema": "data"} id = Column(Integer, primary_key=True, index=True) # --- Alapadatok --- name = Column(String, nullable=False, index=True) # --- Strukturált cím adatok (A kérésedre bontva) --- postal_code = Column(String(10), nullable=True, index=True) # Irányítószám city = Column(String(100), nullable=True, index=True) # Település street = Column(String(255), nullable=True) # Utca és közterület jellege (pl. Diófa utca) house_number = Column(String(50), nullable=True) # Házszám, emelet, ajtó full_address = Column(String, nullable=True) # Az eredeti, egybefüggő cím (ha van) # --- Elérhetőségek --- contact_phone = Column(String, nullable=True) email = Column(String, nullable=True) website = Column(String, nullable=True) # --- Forrás és Azonosítás --- source = Column(String(50), nullable=True, index=True) # Forrás: 'OSM', 'Facebook', stb. external_id = Column(String(100), nullable=True, index=True) # Külső ID (pl. OSM node id) # --- Adatmentés --- # Itt landol a teljes robot-zsákmány minden apró részlettel raw_data = Column(JSONB, server_default=text("'{}'::jsonb")) # --- Státusz és Bizalom --- # status lehet: pending (feldolgozás alatt), enriched (nyomozó által bővített), # duplicate (már megvan), verified (élesítésre kész) status = Column(String(20), server_default=text("'pending'"), index=True) trust_score = Column(Integer, default=0) created_at = Column(DateTime(timezone=True), server_default=func.now())