from datetime import date, datetime from typing import Optional from sqlalchemy import Boolean, Date, DateTime, Integer, String, Text, UniqueConstraint from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column class Base(DeclarativeBase): pass class JobPosting(Base): __tablename__ = "job_postings" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) site_id: Mapped[str] = mapped_column(String(64), nullable=False, index=True) external_job_id: Mapped[Optional[str]] = mapped_column(String(256), nullable=True) title: Mapped[str] = mapped_column(String(512), nullable=False) company: Mapped[Optional[str]] = mapped_column(String(256), nullable=True) location: Mapped[Optional[str]] = mapped_column(String(256), nullable=True) posted_text: Mapped[Optional[str]] = mapped_column(String(128), nullable=True) posted_at_normalized: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) job_url: Mapped[Optional[str]] = mapped_column(Text, nullable=True) salary_text: Mapped[Optional[str]] = mapped_column(String(256), nullable=True) employment_type: Mapped[Optional[str]] = mapped_column(String(128), nullable=True) raw_text: Mapped[Optional[str]] = mapped_column(Text, nullable=True) fingerprint: Mapped[str] = mapped_column(String(64), nullable=False, unique=True) run_date: Mapped[date] = mapped_column(Date, nullable=False, index=True) first_seen_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) last_seen_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) is_new: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) class SiteRun(Base): __tablename__ = "site_runs" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) site_id: Mapped[str] = mapped_column(String(64), nullable=False, index=True) started_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) ended_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) status: Mapped[str] = mapped_column(String(32), nullable=False) items_found: Mapped[int] = mapped_column(Integer, nullable=False, default=0) new_items: Mapped[int] = mapped_column(Integer, nullable=False, default=0) error_summary: Mapped[Optional[str]] = mapped_column(Text, nullable=True) failure_classification: Mapped[Optional[str]] = mapped_column(String(64), nullable=True) trace_path: Mapped[Optional[str]] = mapped_column(Text, nullable=True) screenshot_path: Mapped[Optional[str]] = mapped_column(Text, nullable=True) dom_snapshot_path: Mapped[Optional[str]] = mapped_column(Text, nullable=True) class SiteConfig(Base): __tablename__ = "site_configs" site_id: Mapped[str] = mapped_column(String(64), primary_key=True) enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) repair_needed: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) consecutive_failures: Mapped[int] = mapped_column(Integer, nullable=False, default=0) last_success_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) last_failure_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) notes: Mapped[Optional[str]] = mapped_column(Text, nullable=True) class SiteManifestVersion(Base): __tablename__ = "site_manifest_versions" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) site_id: Mapped[str] = mapped_column(String(64), nullable=False, index=True) version: Mapped[int] = mapped_column(Integer, nullable=False, default=1) generated_by: Mapped[str] = mapped_column(String(64), nullable=False, default="manual") created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) notes: Mapped[Optional[str]] = mapped_column(Text, nullable=True) class Summary(Base): __tablename__ = "summaries" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) run_date: Mapped[date] = mapped_column(Date, nullable=False, index=True) content: Mapped[str] = mapped_column(Text, nullable=False) model_used: Mapped[str] = mapped_column(String(128), nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) class NotificationLog(Base): __tablename__ = "notification_logs" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) run_date: Mapped[date] = mapped_column(Date, nullable=False, index=True) provider: Mapped[str] = mapped_column(String(64), nullable=False) status: Mapped[str] = mapped_column(String(32), nullable=False) error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True) sent_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)