from __future__ import annotations from datetime import datetime from typing import Any from sqlalchemy import Boolean, DateTime, Index, Integer, String, Text, func from sqlalchemy.orm import Mapped, mapped_column from app.core.config import settings from app.db.base import Base from app.db.types import IdMixin, JsonType class ExternalRequestLog(IdMixin, Base): """Журнал обращений к MOEX/ЦБ через шлюз — для разборов «откуда цифра» и отказов шлюза. Только метаданные: без тела ответа и без заголовков (в заголовке — ключ). Исключение — gateway_transaction_id (X-Gravitee-Transaction-Id, D18): по нему команда шлюза находит запрос в логах Gravitee. Журнал только дописывается, поэтому из аудита — created_at/created_by, updated_* здесь не имеют смысла. """ __tablename__ = "external_request_log" __table_args__ = ( Index("ix_external_request_log_created_at", "created_at"), {"schema": settings.DATABASE_SCHEMA} if settings.DATABASE_SCHEMA else {}, ) source: Mapped[str] = mapped_column(String(10), nullable=False) endpoint: Mapped[str] = mapped_column(String(500), nullable=False) params: Mapped[dict[str, Any] | None] = mapped_column(JsonType) http_status: Mapped[int | None] = mapped_column(Integer) duration_ms: Mapped[int] = mapped_column(Integer, nullable=False) ok: Mapped[bool] = mapped_column(Boolean, nullable=False) error: Mapped[str | None] = mapped_column(Text) gateway_transaction_id: Mapped[str | None] = mapped_column(String(100)) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False ) created_by: Mapped[str] = mapped_column(String(255), nullable=False)