frontend admin refakctorálás

This commit is contained in:
Roo
2026-07-08 08:03:57 +00:00
parent 07b59032ce
commit 2e0abc62a7
455 changed files with 14428 additions and 21651 deletions

View File

@@ -42,6 +42,7 @@ from .identity.social import ServiceProvider, Vote, Competition, UserScore, Serv
# 9. Rendszer, Gamification és egyebek
from .gamification.gamification import PointRule, LevelConfig, UserStats, Badge, UserBadge, PointsLedger, UserContribution, Season
from .gamification.validation_rule import ValidationRule
from .system.system import SystemParameter, ParameterScope, InternalNotification, SystemServiceStaging
from .system.rbac import SystemRole, SystemPermission, SystemRolePermission
@@ -75,7 +76,7 @@ __all__ = [
"Asset", "AssetCatalog", "AssetCost", "AssetEvent", "AssetAssignment", "AssetFinancials",
"AssetTelemetry", "AssetReview", "ExchangeRate", "CatalogDiscovery", "OdometerReading",
"Address", "GeoPostalCode", "GeoStreet", "GeoStreetType", "Branch",
"PointRule", "LevelConfig", "UserStats", "Badge", "UserBadge", "Rating", "PointsLedger", "UserContribution",
"PointRule", "LevelConfig", "UserStats", "Badge", "UserBadge", "Rating", "PointsLedger", "UserContribution", "ValidationRule",
"SystemParameter", "ParameterScope", "InternalNotification",

View File

@@ -1,7 +1,7 @@
# /opt/docker/dev/service_finder/backend/app/models/core_logic.py
from typing import Optional, List, Any
from datetime import datetime # Python saját típusa a típusjelöléshez
from sqlalchemy import String, Integer, ForeignKey, Boolean, DateTime, Numeric, text, Float
from sqlalchemy import String, Integer, ForeignKey, Boolean, DateTime, Numeric, text, Float, Index
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.sql import func
@@ -243,11 +243,17 @@ class ServiceCatalog(Base):
Tábla: system.service_catalog
"""
__tablename__ = "service_catalog"
__table_args__ = {"schema": "system"}
__table_args__ = (
Index('idx_service_catalog_name_i18n', 'name_i18n', postgresql_using='gin'),
{"schema": "system"}
)
id: Mapped[int] = mapped_column(Integer, primary_key=True)
service_code: Mapped[str] = mapped_column(String, unique=True, index=True, nullable=False) # pl. 'SRV_DATA_EXPORT'
name: Mapped[str] = mapped_column(String, nullable=False)
description: Mapped[Optional[str]] = mapped_column(String)
# --- 🏗️ i18n JSONB Migration (Phase 1) ---
name_i18n: Mapped[dict] = mapped_column(JSONB, nullable=False, server_default=text("'{\"hu\": \"\"}'::jsonb"))
description_i18n: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True)
credit_cost: Mapped[int] = mapped_column(Integer, default=0) # alapértelmezett ár kreditben
is_active: Mapped[bool] = mapped_column(Boolean, default=True)

View File

@@ -9,6 +9,7 @@ from .gamification import (
UserContribution,
Season,
)
from .validation_rule import ValidationRule
__all__ = [
"PointRule",
@@ -19,4 +20,5 @@ __all__ = [
"UserBadge",
"UserContribution",
"Season",
"ValidationRule",
]

View File

@@ -0,0 +1,53 @@
# /opt/docker/dev/service_finder/backend/app/models/gamification/validation_rule.py
"""
ValidationRule model — Gamification schema.
Stores dynamic global provider validation rules (thresholds) that drive
the ValidationEngine. Rules are key-value pairs with integer values,
seeded at initialization and editable via the admin panel.
Schema: gamification.validation_rules
"""
from typing import Optional
from datetime import datetime
from sqlalchemy import String, Integer, DateTime, func
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class ValidationRule(Base):
"""
Global provider validation rules / thresholds.
Each row defines a single rule_key → rule_value mapping used by
the ValidationEngine to compute trust scores and auto-approval
thresholds for service providers.
Seed data (base rules):
BOT_BASE_SCORE = 20 # Default trust score for robot-discovered entries
FIRST_ENTRY_SCORE = 40 # Score awarded for the first user entry
USER_CONFIRM_BASE = 20 # Base score per user confirmation vote
AUTO_APPROVE_THRESHOLD = 80 # Minimum validation_level to auto-promote
"""
__tablename__ = "validation_rules"
__table_args__ = {"schema": "gamification", "extend_existing": True}
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
rule_key: Mapped[str] = mapped_column(
String(100), unique=True, nullable=False, index=True,
comment="Unique rule identifier, e.g. 'BOT_BASE_SCORE'"
)
rule_value: Mapped[int] = mapped_column(
Integer, nullable=False, default=0,
comment="Integer value for this rule (score, threshold, etc.)"
)
description: Mapped[Optional[str]] = mapped_column(
String(500), nullable=True,
comment="Human-readable description of what this rule controls"
)
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()
)

View File

@@ -57,7 +57,7 @@ class Address(Base):
# Robot és térképes funkciók számára
latitude: Mapped[Optional[float]] = mapped_column(Float)
longitude: Mapped[Optional[float]] = mapped_column(Float)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), default=func.now())
# Kapcsolat az irányítószám táblához (zip/city lekéréshez)
postal_code: Mapped[Optional["GeoPostalCode"]] = relationship("GeoPostalCode", lazy="joined")

View File

@@ -2,13 +2,16 @@
import enum
import uuid
from datetime import datetime
from typing import Optional, List
from typing import Optional, List, TYPE_CHECKING
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, JSONB, ARRAY
from sqlalchemy.sql import func
from app.database import Base
if TYPE_CHECKING:
from app.models.identity.address import Address
class ModerationStatus(str, enum.Enum):
pending = "pending"
approved = "approved"
@@ -34,7 +37,12 @@ class ServiceProvider(Base):
address: Mapped[str] = mapped_column(String, nullable=False)
category: Mapped[Optional[str]] = mapped_column(String)
# === P0 HYBRID VENDOR REFACTOR: Atomizált címmezők ===
# === P0 ADDRESS UNIFICATION: Normalizált cím FK a system.addresses táblához ===
address_id: Mapped[Optional[uuid.UUID]] = mapped_column(
PG_UUID(as_uuid=True), ForeignKey("system.addresses.id"), nullable=True
)
# === P0 HYBRID VENDOR REFACTOR: Atomizált címmezők (DEPRECATED - Phase 3-ban törlendő) ===
city: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
address_zip: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)
address_street_name: Mapped[Optional[str]] = mapped_column(String(150), nullable=True)
@@ -68,6 +76,11 @@ class ServiceProvider(Base):
JSONB, server_default=text("'{}'::jsonb"), nullable=True
)
# === P0 ADDRESS UNIFICATION: Kapcsolat a normalizált címhez ===
address_rel: Mapped[Optional["Address"]] = relationship(
"Address", foreign_keys=[address_id], lazy="selectin"
)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
class Vote(Base):

View File

@@ -35,7 +35,7 @@ class ServiceProfile(Base):
parent_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("marketplace.service_profiles.id"))
fingerprint: Mapped[str] = mapped_column(String(255), index=True, nullable=False)
location: Mapped[Any] = mapped_column(Geometry(geometry_type='POINT', srid=4326, spatial_index=False), index=True)
location: Mapped[Optional[Any]] = mapped_column(Geometry(geometry_type='POINT', srid=4326, spatial_index=False), nullable=True, index=True)
status: Mapped[ServiceStatus] = mapped_column(
SQLEnum(ServiceStatus, name="service_status", schema="marketplace"),
@@ -105,6 +105,7 @@ class ExpertiseTag(Base):
__tablename__ = "expertise_tags"
__table_args__ = (
Index('idx_expertise_path', 'path'),
Index('idx_expertise_tags_name_i18n', 'name_i18n', postgresql_using='gin'),
{"schema": "marketplace"}
)
@@ -112,6 +113,9 @@ class ExpertiseTag(Base):
key: Mapped[str] = mapped_column(String(50), unique=True, index=True)
name_hu: Mapped[Optional[str]] = mapped_column(String(100))
name_en: Mapped[Optional[str]] = mapped_column(String(100))
# --- 🏗️ i18n JSONB Migration (Phase 1) ---
name_i18n: Mapped[dict] = mapped_column(JSONB, nullable=False, server_default=text("'{\"hu\": \"\"}'::jsonb"))
description_i18n: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True)
name_translations: Mapped[Any] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
category: Mapped[Optional[str]] = mapped_column(String(30), index=True)

View File

@@ -1,8 +1,9 @@
import uuid
from datetime import datetime
from typing import Optional, Any
from sqlalchemy import String, Integer, DateTime, text, Boolean, Float, Text, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.dialects.postgresql import JSONB, UUID as PG_UUID
from sqlalchemy.sql import func
from app.database import Base # MB 2.0 Standard: Központi bázis használata
@@ -75,10 +76,14 @@ class ServiceStaging(Base):
# 9. ⚠️ EXTRA OSZLOP: audit_trail
audit_trail: Mapped[Optional[dict]] = mapped_column(JSONB)
# 10. ⚠️ P0 BUGFIX: address_id — FK to system.addresses (UUID)
# The column exists in the database but was missing from the model.
address_id: Mapped[Optional[uuid.UUID]] = mapped_column(PG_UUID(as_uuid=True), ForeignKey("system.addresses.id"), nullable=True)
# Időbélyegek
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
# 10. ⚠️ EXTRA OSZLOP: updated_at
# 11. ⚠️ EXTRA OSZLOP: updated_at
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), onupdate=func.now())
class DiscoveryParameter(Base):

View File

@@ -165,10 +165,13 @@ class BodyTypeDictionary(Base):
__tablename__ = "dict_body_types"
__table_args__ = (
UniqueConstraint('vehicle_class', 'code', name='uix_body_type_class_code'),
Index('idx_dict_body_types_name_i18n', 'name_i18n', postgresql_using='gin'),
{"schema": "vehicle"}
)
id: Mapped[int] = mapped_column(Integer, primary_key=True)
vehicle_class: Mapped[str] = mapped_column(String(50), index=True, nullable=False)
code: Mapped[str] = mapped_column(String(50), nullable=False)
name_hu: Mapped[str] = mapped_column(String(100), nullable=False)
name_hu: Mapped[str] = mapped_column(String(100), nullable=False)
# --- 🏗️ i18n JSONB Migration (Phase 1) ---
name_i18n: Mapped[dict] = mapped_column(JSONB, nullable=False, server_default=text("'{\"hu\": \"\"}'::jsonb"))