Cleanup: MB 2.0 Gap Analysis előtti állapot (adatok kizárva)

This commit is contained in:
2026-02-23 09:44:02 +01:00
parent 5757754aae
commit 893f39fa15
74 changed files with 34239 additions and 2834 deletions

View File

@@ -1,6 +1,6 @@
import uuid
from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, JSON, text, Text, Float
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, JSON, text, Text, Float, Index, Numeric
from sqlalchemy.orm import relationship, backref
from sqlalchemy.dialects.postgresql import UUID as PG_UUID, JSONB
from geoalchemy2 import Geometry # PostGIS támogatás
from sqlalchemy.sql import func
@@ -8,45 +8,78 @@ from app.db.base_class import Base
class ServiceProfile(Base):
"""
Szerviz szolgáltató kiterjesztett adatai.
Szerviz szolgáltató kiterjesztett adatai (v1.3.1).
Egy Organization-höz (org_type='service') kapcsolódik.
Támogatja a hierarchiát (Franchise/Telephely) és az automatizált dúsítást.
"""
__tablename__ = "service_profiles"
__table_args__ = {"schema": "data"}
__table_args__ = (
# Egyedi ujjlenyomat index a robot számára a duplikációk elkerülésére
Index('idx_service_fingerprint', 'fingerprint', unique=True),
{"schema": "data"}
)
id = Column(Integer, primary_key=True, index=True)
# --- KAPCSOLAT A CÉGES IKERHEZ (Twin) ---
organization_id = Column(Integer, ForeignKey("data.organizations.id"), unique=True)
# --- HIERARCHIA (Fa struktúra) ---
# Ez tárolja a szülő egység ID-ját (pl. hálózat központja)
parent_id = Column(Integer, ForeignKey("data.service_profiles.id"), nullable=True)
# --- ROBOT IDENTITÁS ---
# Normalize(Név + Város + Utca) hash, hogy ne legyen duplikáció
fingerprint = Column(String(255), nullable=False, index=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
# Állapotkezelés: ghost (robot találta), active, flagged, inactive
status = Column(String(20), server_default=text("'ghost'"), index=True)
last_audit_at = Column(DateTime(timezone=True), server_default=func.now())
last_audit_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
# --- MAGÁNNYOMOZÓ (Deep Enrichment) ADATOK ---
# --- GOOGLE ÉS KÜLSŐ 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"]}
# --- MÉLYFÚRÁS (Deep Enrichment) ADATOK ---
# AI elemzés: {"tone": "barátságos", "pricing": "közép", "reliability": "magas"}
vibe_analysis = Column(JSONB, server_default=text("'{}'::jsonb"))
# Közösségi háló: {"facebook": "url", "tiktok": "url", "insta": "url"}
social_links = Column(JSONB, server_default=text("'{}'::jsonb"))
# Speciális szűrő címkék: {"brands": ["Yamaha", "Suzuki"], "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"))
verification_log = Column(JSONB, server_default=text("'{}'::jsonb"))
opening_hours = Column(JSON, server_default=text("'{}'::jsonb"))
# --- ELÉRHETŐSÉG ---
opening_hours = Column(JSONB, server_default=text("'{}'::jsonb"))
contact_phone = Column(String)
contact_email = Column(String)
website = Column(String)
bio = Column(Text)
# Kapcsolatok
organization = relationship("Organization")
# --- KAPCSOLATOK ---
organization = relationship("Organization", back_populates="service_profile")
expertises = relationship("ServiceExpertise", back_populates="service")
# --- ÖNMAGÁRA HIVATKOZÓ KAPCSOLAT (Hierarchia) ---
sub_services = relationship(
"ServiceProfile",
backref=backref("parent_service", remote_side=[id]),
cascade="all, delete-orphan"
)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
class ExpertiseTag(Base):
"""Szakmai szempontok taxonómiája."""
__tablename__ = "expertise_tags"
@@ -74,56 +107,57 @@ class ServiceExpertise(Base):
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"}
__table_args__ = (
Index('idx_staging_fingerprint', 'fingerprint', unique=True),
{"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) ---
# --- Strukturált cím adatok ---
postal_code = Column(String(10), index=True)
city = Column(String(100), index=True)
street_name = Column(String(150))
street_type = Column(String(50)) # utca, út, tér...
street_type = Column(String(50))
house_number = Column(String(20))
stairwell = Column(String(20)) # lépcsőház
floor = Column(String(20)) # emelet
door = Column(String(20)) # ajtó
hrsz = Column(String(50)) # helyrajzi szám
stairwell = Column(String(20))
floor = Column(String(20))
door = Column(String(20))
hrsz = Column(String(50))
full_address = Column(String) # Eredeti string (audit célból)
# --- Elérhetőségek ---
full_address = Column(String)
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)
source = Column(String(50), nullable=True, index=True)
external_id = Column(String(100), nullable=True, index=True)
# Robot ujjlenyomat a Staging szintű deduplikációhoz
fingerprint = Column(String(255), nullable=False)
# --- 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())
class DiscoveryParameter(Base):
"""Robot vezérlési paraméterek."""
__tablename__ = "discovery_parameters"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True)
city = Column(String(100), nullable=False)
keyword = Column(String(100), nullable=False) # pl. "autóvillamosság"
keyword = Column(String(100), nullable=False)
country_code = Column(String(2), default="HU")
is_active = Column(Boolean, default=True)
last_run_at = Column(DateTime(timezone=True))