feat: implement hybrid address system and premium search logic

- Added centralized, self-learning GeoService (ZIP, City, Street)
- Implemented Hybrid Address Management (Centralized table + Denormalized fields)
- Fixed Gamification logic (PointsLedger field names & filtering)
- Added address autocomplete and two-tier (Free/Premium) search API
- Synchronized UserStats and PointsLedger schemas
This commit is contained in:
2026-02-08 16:26:39 +00:00
parent 4e14d57bf6
commit 451900ae1a
41 changed files with 764 additions and 515 deletions

View File

@@ -4,7 +4,7 @@ from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, J
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from app.db.base import Base # <--- JAVÍTVA: base_class helyett base
from app.db.base import Base
class UserRole(str, enum.Enum):
admin = "admin"
@@ -25,12 +25,14 @@ class Person(Base):
mothers_name = Column(String, nullable=True)
birth_place = Column(String, nullable=True)
birth_date = Column(DateTime, nullable=True)
phone = Column(String, nullable=True)
# JSONB mezők az okmányoknak és orvosi adatoknak
identity_docs = Column(JSON, server_default=text("'{}'::jsonb"))
medical_emergency = Column(JSON, server_default=text("'{}'::jsonb"))
ice_contact = Column(JSON, server_default=text("'{}'::jsonb"))
# Ez a mező kell a 2-lépcsős regisztrációhoz
# KYC státusz
is_active = Column(Boolean, default=False, nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
@@ -55,7 +57,6 @@ class User(Base):
person = relationship("Person", back_populates="users")
wallet = relationship("Wallet", back_populates="user", uselist=False)
# Kapcsolat lusta betöltéssel a mapper hiba ellen
owned_organizations = relationship("Organization", back_populates="owner", lazy="select")
created_at = Column(DateTime(timezone=True), server_default=func.now())
@@ -78,7 +79,7 @@ class VerificationToken(Base):
id = Column(Integer, primary_key=True, index=True)
token = Column(UUID(as_uuid=True), default=uuid.uuid4, unique=True, nullable=False)
user_id = Column(Integer, ForeignKey("data.users.id", ondelete="CASCADE"), nullable=False)
token_type = Column(String(20), nullable=False) # 'registration' or 'password_reset'
token_type = Column(String(20), nullable=False) # 'registration' vagy 'password_reset'
created_at = Column(DateTime(timezone=True), server_default=func.now())
expires_at = Column(DateTime(timezone=True), nullable=False)
is_used = Column(Boolean, default=False)