Add Sejoli tryout JSON snapshot importer

This commit is contained in:
dwindown
2026-04-02 17:04:01 +07:00
parent 51c577be05
commit b4ebdc9c4f
7 changed files with 910 additions and 1 deletions

View File

@@ -0,0 +1,103 @@
"""
Snapshot archive for imported external tryout payloads.
Stores each imported JSON export so the backend can trace source changes
without treating the source file itself as the system of record.
"""
from datetime import datetime
from typing import Optional
from sqlalchemy import DateTime, ForeignKey, Integer, JSON, String, func
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class TryoutImportSnapshot(Base):
__tablename__ = "tryout_import_snapshots"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
website_id: Mapped[int] = mapped_column(
ForeignKey("websites.id", ondelete="CASCADE", onupdate="CASCADE"),
nullable=False,
index=True,
comment="Website identifier",
)
source_tryout_id: Mapped[str] = mapped_column(
String(255),
nullable=False,
index=True,
comment="External source tryout identifier",
)
source_key: Mapped[str] = mapped_column(
String(255),
nullable=False,
comment="External tryout object key in source payload",
)
title: Mapped[str] = mapped_column(
String(255),
nullable=False,
comment="Imported tryout title",
)
source_permalink: Mapped[Optional[str]] = mapped_column(
String(1024),
nullable=True,
comment="Imported source permalink",
)
source_status: Mapped[Optional[str]] = mapped_column(
String(50),
nullable=True,
comment="Imported source status",
)
exported_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True),
nullable=True,
comment="Timestamp from source export metadata",
)
source_created_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True),
nullable=True,
comment="Source tryout created timestamp",
)
source_modified_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True),
nullable=True,
comment="Source tryout modified timestamp",
)
exported_by: Mapped[Optional[str]] = mapped_column(
String(255),
nullable=True,
comment="Source exporter identity",
)
question_count: Mapped[int] = mapped_column(
Integer,
nullable=False,
default=0,
comment="Number of questions in imported payload",
)
result_count: Mapped[int] = mapped_column(
Integer,
nullable=False,
default=0,
comment="Number of result rows in imported payload",
)
payload_checksum: Mapped[str] = mapped_column(
String(64),
nullable=False,
comment="Checksum for the imported payload",
)
raw_payload: Mapped[dict] = mapped_column(
JSON,
nullable=False,
comment="Original imported payload",
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, server_default=func.now()
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
server_default=func.now(),
onupdate=func.now(),
)