átlagos kiegészítséek jó sok
This commit is contained in:
12
backend/app/models/system/__init__.py
Normal file
12
backend/app/models/system/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# system package barrel
|
||||
from .system import SystemParameter, ParameterScope, InternalNotification, SystemServiceStaging
|
||||
from .audit import SecurityAuditLog, OperationalLog, ProcessLog, FinancialLedger, WalletType, LedgerStatus, LedgerEntryType
|
||||
from .document import Document
|
||||
from .translation import Translation
|
||||
from .legal import LegalDocument, LegalAcceptance
|
||||
|
||||
__all__ = [
|
||||
"SystemParameter", "InternalNotification", "SystemServiceStaging",
|
||||
"SecurityAuditLog", "ProcessLog", "FinancialLedger", "WalletType", "LedgerStatus", "LedgerEntryType",
|
||||
"Document", "Translation", "LegalDocument", "LegalAcceptance"
|
||||
]
|
||||
115
backend/app/models/system/audit.py
Executable file
115
backend/app/models/system/audit.py
Executable file
@@ -0,0 +1,115 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/models/system/audit.py
|
||||
import enum
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any, Optional
|
||||
from sqlalchemy import String, DateTime, JSON, ForeignKey, text, Numeric, Boolean, BigInteger, Integer
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.dialects.postgresql import UUID as PG_UUID, ENUM as PG_ENUM
|
||||
from app.database import Base
|
||||
|
||||
class SecurityAuditLog(Base):
|
||||
""" Kiemelt biztonsági események és a 4-szem elv naplózása. """
|
||||
__tablename__ = "security_audit_logs"
|
||||
__table_args__ = {"schema": "audit"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
action: Mapped[Optional[str]] = mapped_column(String(50)) # 'ROLE_CHANGE', 'MANUAL_CREDIT_ADJUST'
|
||||
|
||||
actor_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
|
||||
target_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
|
||||
confirmed_by_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"), nullable=True)
|
||||
|
||||
is_critical: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
payload_before: Mapped[Any] = mapped_column(JSON)
|
||||
payload_after: Mapped[Any] = mapped_column(JSON)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
class OperationalLog(Base):
|
||||
""" Felhasználói szintű napi üzemi események (Audit Trail). """
|
||||
__tablename__ = "operational_logs"
|
||||
__table_args__ = {"schema": "audit"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
||||
user_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id", ondelete="SET NULL"))
|
||||
action: Mapped[str] = mapped_column(String(100), nullable=False) # pl. "ADD_VEHICLE"
|
||||
resource_type: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
resource_id: Mapped[Optional[str]] = mapped_column(String(100))
|
||||
details: Mapped[Any] = mapped_column(JSON, server_default=text("'{}'::jsonb"))
|
||||
ip_address: Mapped[Optional[str]] = mapped_column(String(45))
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
class ProcessLog(Base):
|
||||
""" Robotok és háttérfolyamatok futási naplója (A reggeli jelentésekhez). """
|
||||
__tablename__ = "process_logs"
|
||||
__table_args__ = {"schema": "audit"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
process_name: Mapped[str] = mapped_column(String(100), index=True) # 'Master-Enricher'
|
||||
start_time: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
end_time: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
|
||||
items_processed: Mapped[int] = mapped_column(Integer, default=0)
|
||||
items_failed: Mapped[int] = mapped_column(Integer, default=0)
|
||||
details: Mapped[Any] = mapped_column(JSON, server_default=text("'{}'::jsonb"))
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
|
||||
class LedgerEntryType(str, enum.Enum):
|
||||
DEBIT = "DEBIT"
|
||||
CREDIT = "CREDIT"
|
||||
|
||||
|
||||
class WalletType(str, enum.Enum):
|
||||
EARNED = "EARNED"
|
||||
PURCHASED = "PURCHASED"
|
||||
SERVICE_COINS = "SERVICE_COINS"
|
||||
VOUCHER = "VOUCHER"
|
||||
|
||||
|
||||
class LedgerStatus(str, enum.Enum):
|
||||
PENDING = "PENDING"
|
||||
SUCCESS = "SUCCESS"
|
||||
FAILED = "FAILED"
|
||||
REFUNDED = "REFUNDED"
|
||||
REFUND = "REFUND"
|
||||
|
||||
|
||||
class FinancialLedger(Base):
|
||||
""" Minden pénz- és kreditmozgás központi naplója. Billing Engine alapja. """
|
||||
__tablename__ = "financial_ledger"
|
||||
__table_args__ = {"schema": "audit"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
user_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
|
||||
person_id: Mapped[Optional[int]] = mapped_column(BigInteger, ForeignKey("identity.persons.id"))
|
||||
amount: Mapped[float] = mapped_column(Numeric(18, 4), nullable=False)
|
||||
currency: Mapped[Optional[str]] = mapped_column(String(10))
|
||||
transaction_type: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
related_agent_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
|
||||
details: Mapped[Any] = mapped_column(JSON, server_default=text("'{}'::jsonb"))
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
# Új mezők double‑entry és okos levonáshoz
|
||||
entry_type: Mapped[LedgerEntryType] = mapped_column(
|
||||
PG_ENUM(LedgerEntryType, name="ledger_entry_type", schema="audit"),
|
||||
nullable=False
|
||||
)
|
||||
balance_after: Mapped[Optional[float]] = mapped_column(Numeric(18, 4))
|
||||
wallet_type: Mapped[Optional[WalletType]] = mapped_column(
|
||||
PG_ENUM(WalletType, name="wallet_type", schema="audit")
|
||||
)
|
||||
# Economy 1: számlázási mezők
|
||||
issuer_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("finance.issuers.id"), nullable=True)
|
||||
invoice_status: Mapped[Optional[str]] = mapped_column(String(50), default="PENDING")
|
||||
tax_amount: Mapped[Optional[float]] = mapped_column(Numeric(18, 4))
|
||||
gross_amount: Mapped[Optional[float]] = mapped_column(Numeric(18, 4))
|
||||
net_amount: Mapped[Optional[float]] = mapped_column(Numeric(18, 4))
|
||||
transaction_id: Mapped[uuid.UUID] = mapped_column(
|
||||
PG_UUID(as_uuid=True), default=uuid.uuid4, nullable=False, index=True
|
||||
)
|
||||
status: Mapped[LedgerStatus] = mapped_column(
|
||||
PG_ENUM(LedgerStatus, name="ledger_status", schema="audit"),
|
||||
default=LedgerStatus.SUCCESS,
|
||||
nullable=False
|
||||
)
|
||||
42
backend/app/models/system/document.py
Executable file
42
backend/app/models/system/document.py
Executable file
@@ -0,0 +1,42 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/models/system/document.py
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from sqlalchemy import String, Integer, Boolean, DateTime, ForeignKey, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID as PG_UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from sqlalchemy.sql import func
|
||||
from app.database import Base # MB 2.0: Egységesített Base a szinkronitáshoz
|
||||
|
||||
class Document(Base):
|
||||
""" NAS alapú dokumentumtár metaadatai. """
|
||||
__tablename__ = "documents"
|
||||
__table_args__ = {"schema": "system"}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
parent_type: Mapped[str] = mapped_column(String(20)) # 'organization' vagy 'asset'
|
||||
parent_id: Mapped[str] = mapped_column(String(50), index=True)
|
||||
doc_type: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
|
||||
original_name: Mapped[str] = mapped_column(String(255))
|
||||
file_hash: Mapped[str] = mapped_column(String(64))
|
||||
file_ext: Mapped[str] = mapped_column(String(10), default="webp")
|
||||
mime_type: Mapped[str] = mapped_column(String(100), default="image/webp")
|
||||
file_size: Mapped[Optional[int]] = mapped_column(Integer)
|
||||
|
||||
has_thumbnail: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
thumbnail_path: Mapped[Optional[str]] = mapped_column(String(255))
|
||||
|
||||
uploaded_by: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
# =========================================================================
|
||||
# THOUGHT PROCESS & ARCHITECTURE DECISIONS (2026-03-04)
|
||||
# =========================================================================
|
||||
# Probléma: Az `ocr_robot.py` (Robot 3) módosítani próbálta a dokumentumok
|
||||
# állapotát és menteni akarta az AI eredményeket, de a mezők hiányoztak.
|
||||
# =========================================================================
|
||||
|
||||
status: Mapped[str] = mapped_column(String(50), default="uploaded", index=True)
|
||||
ocr_data: Mapped[Optional[str]] = mapped_column(Text)
|
||||
error_log: Mapped[Optional[str]] = mapped_column(Text)
|
||||
33
backend/app/models/system/legal.py
Executable file
33
backend/app/models/system/legal.py
Executable file
@@ -0,0 +1,33 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/models/system/legal.py
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from sqlalchemy import Integer, String, Text, DateTime, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from sqlalchemy.sql import func
|
||||
from app.db.base_class import Base
|
||||
|
||||
class LegalDocument(Base):
|
||||
__tablename__ = "legal_documents"
|
||||
__table_args__ = {"schema": "system"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
||||
title: Mapped[Optional[str]] = mapped_column(String(255))
|
||||
content: Mapped[str] = mapped_column(Text)
|
||||
version: Mapped[str] = mapped_column(String(20))
|
||||
|
||||
region_code: Mapped[str] = mapped_column(String(5), default="HU")
|
||||
language: Mapped[str] = mapped_column(String(5), default="hu")
|
||||
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
class LegalAcceptance(Base):
|
||||
__tablename__ = "legal_acceptances"
|
||||
__table_args__ = {"schema": "identity"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
||||
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("identity.users.id"))
|
||||
document_id: Mapped[int] = mapped_column(Integer, ForeignKey("system.legal_documents.id"))
|
||||
accepted_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
ip_address: Mapped[Optional[str]] = mapped_column(String(45))
|
||||
user_agent: Mapped[Optional[str]] = mapped_column(Text)
|
||||
91
backend/app/models/system/system.py
Executable file
91
backend/app/models/system/system.py
Executable file
@@ -0,0 +1,91 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/models/system/system.py
|
||||
import uuid
|
||||
from datetime import datetime, date
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
from sqlalchemy import String, Integer, Boolean, DateTime, text, UniqueConstraint, ForeignKey, Text, Enum as SQLEnum, Date
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
||||
from sqlalchemy.sql import func
|
||||
from app.database import Base
|
||||
|
||||
class ParameterScope(str, Enum):
|
||||
GLOBAL = "global"
|
||||
COUNTRY = "country"
|
||||
REGION = "region"
|
||||
USER = "user"
|
||||
|
||||
class SystemParameter(Base):
|
||||
""" Dinamikus konfigurációs motor (Global -> Org -> User). """
|
||||
__tablename__ = "system_parameters"
|
||||
__table_args__ = (
|
||||
UniqueConstraint('key', 'scope_level', 'scope_id', name='uix_param_scope'),
|
||||
{"schema": "system", "extend_existing": True}
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
key: Mapped[str] = mapped_column(String, index=True)
|
||||
category: Mapped[str] = mapped_column(String, server_default="general", index=True)
|
||||
value: Mapped[dict] = mapped_column(JSONB, nullable=False)
|
||||
|
||||
scope_level: Mapped[ParameterScope] = mapped_column(SQLEnum(ParameterScope, name="parameter_scope", schema="system"), server_default=ParameterScope.GLOBAL.value, index=True)
|
||||
scope_id: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
description: Mapped[Optional[str]] = mapped_column(String)
|
||||
last_modified_by: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), onupdate=func.now(), server_default=func.now())
|
||||
|
||||
class InternalNotification(Base):
|
||||
"""
|
||||
Belső értesítési központ.
|
||||
Ezek az üzenetek várják a felhasználót belépéskor.
|
||||
"""
|
||||
__tablename__ = "internal_notifications"
|
||||
__table_args__ = ({"schema": "system", "extend_existing": True})
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||
user_id: Mapped[int] = mapped_column(ForeignKey("identity.users.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||
|
||||
title: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
message: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
category: Mapped[str] = mapped_column(String(50), server_default="info")
|
||||
priority: Mapped[str] = mapped_column(String(20), server_default="medium")
|
||||
|
||||
read_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
data: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True)
|
||||
|
||||
is_read: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
|
||||
class SystemServiceStaging(Base):
|
||||
""" Robot 1.3 (Scout) által talált nyers szerviz adatok. """
|
||||
__tablename__ = "service_staging"
|
||||
__table_args__ = {"schema": "system"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(255), index=True)
|
||||
source: Mapped[str] = mapped_column(String(50))
|
||||
external_id: Mapped[Optional[str]] = mapped_column(String(100), index=True)
|
||||
fingerprint: Mapped[str] = mapped_column(String(64), unique=True, index=True)
|
||||
|
||||
postal_code: Mapped[Optional[str]] = mapped_column(String(20), index=True)
|
||||
city: Mapped[str] = mapped_column(String(100), index=True)
|
||||
full_address: Mapped[Optional[str]] = mapped_column(String(500))
|
||||
contact_phone: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
website: Mapped[Optional[str]] = mapped_column(String(255))
|
||||
contact_email: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
||||
|
||||
raw_data: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
status: Mapped[str] = mapped_column(String(20), default="pending", index=True)
|
||||
trust_score: Mapped[int] = mapped_column(Integer, default=30)
|
||||
|
||||
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())
|
||||
|
||||
# JAVÍTÁS: Ezeket az oszlopokat vissza kell tenni, mert az audit szerint
|
||||
# az adatbázisban léteznek a system.service_staging táblában.
|
||||
read_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
data: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True)
|
||||
|
||||
27
backend/app/models/system/translation.py
Executable file
27
backend/app/models/system/translation.py
Executable file
@@ -0,0 +1,27 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/models/system/translation.py
|
||||
from sqlalchemy import String, Integer, Text, Boolean, text
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
# MB 2.0: A központi aszinkron adatbázis motorból húzzuk be a Base-t
|
||||
from app.database import Base
|
||||
|
||||
class Translation(Base):
|
||||
"""
|
||||
Többnyelvűséget támogató tábla a felületi elemekhez és dinamikus tartalmakhoz.
|
||||
"""
|
||||
__tablename__ = "translations"
|
||||
__table_args__ = {"schema": "system"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
||||
|
||||
# A fordítandó kulcs (pl. 'NAV_DASHBOARD' vagy 'ERR_USER_NOT_FOUND')
|
||||
key: Mapped[str] = mapped_column(String(255), index=True)
|
||||
|
||||
# Nyelvi kód (pl: 'hu', 'en', 'de')
|
||||
lang: Mapped[str] = mapped_column(String(5), index=True)
|
||||
|
||||
# A tényleges fordított szöveg
|
||||
value: Mapped[str] = mapped_column(Text)
|
||||
|
||||
# --- JAVÍTÁS: A diagnosztika által hiányolt publikációs állapot ---
|
||||
is_published: Mapped[bool] = mapped_column(Boolean, default=True, server_default=text("true"))
|
||||
Reference in New Issue
Block a user