frontend admin refakctorálás
This commit is contained in:
@@ -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",
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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",
|
||||
]
|
||||
53
backend/app/models/gamification/validation_rule.py
Normal file
53
backend/app/models/gamification/validation_rule.py
Normal 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()
|
||||
)
|
||||
@@ -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")
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"))
|
||||
Reference in New Issue
Block a user