thereisnohr / src /storage /models.py
jbeiroa's picture
Initial clean deploy of demo app
74711df
"""Persistence utilities, ORM models, and repository implementations."""
from datetime import datetime, timezone
from pgvector.sqlalchemy import Vector
from sqlalchemy import (
CheckConstraint,
DateTime,
Float,
ForeignKey,
ForeignKeyConstraint,
Index,
Integer,
String,
Text,
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from src.storage.db import Base
class Candidate(Base):
"""Data model for candidate values."""
__tablename__ = "candidates"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
external_id: Mapped[str | None] = mapped_column(String(128), index=True, nullable=True)
name: Mapped[str | None] = mapped_column(String(255), nullable=True)
email: Mapped[str | None] = mapped_column(String(255), nullable=True)
phone: Mapped[str | None] = mapped_column(String(64), nullable=True)
links: Mapped[list[str] | None] = mapped_column(JSONB, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
)
resumes: Mapped[list["Resume"]] = relationship(back_populates="candidate")
class Resume(Base):
"""Data model for resume values."""
__tablename__ = "resumes"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
candidate_id: Mapped[int] = mapped_column(ForeignKey("candidates.id"), nullable=False)
source_file: Mapped[str] = mapped_column(String(512), nullable=False)
content_hash: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
raw_text: Mapped[str] = mapped_column(Text, nullable=False)
parsed_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
signals_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
language: Mapped[str | None] = mapped_column(String(16), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
)
candidate: Mapped[Candidate] = relationship(back_populates="resumes")
sections: Mapped[list["ResumeSection"]] = relationship(back_populates="resume")
class ResumeSection(Base):
"""Data model for resumesection values."""
__tablename__ = "resume_sections"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
resume_id: Mapped[int] = mapped_column(ForeignKey("resumes.id"), nullable=False)
section_type: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
content: Mapped[str] = mapped_column(Text, nullable=False)
tokens: Mapped[int | None] = mapped_column(Integer, nullable=True)
metadata_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
resume: Mapped[Resume] = relationship(back_populates="sections")
class JobPosting(Base):
"""Data model for jobposting values."""
__tablename__ = "job_postings"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
title: Mapped[str] = mapped_column(String(255), nullable=False)
description: Mapped[str] = mapped_column(Text, nullable=False)
requirements_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
)
class Embedding(Base):
"""Data model for embedding values."""
__tablename__ = "embeddings"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
owner_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
model: Mapped[str] = mapped_column(String(128), nullable=False)
dimensions: Mapped[int] = mapped_column(Integer, nullable=False)
vector: Mapped[list[float]] = mapped_column(Vector(), nullable=False)
text_hash: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
)
__table_args__ = (
CheckConstraint("dimensions > 0", name="ck_embeddings_dimensions_positive"),
CheckConstraint(
"dimensions = vector_dims(vector)", name="ck_embeddings_dimensions_match_vector"
),
ForeignKeyConstraint(
["model", "dimensions"],
["embedding_models.model", "embedding_models.dimensions"],
name="fk_embeddings_model_dimensions",
),
Index("ix_embeddings_owner", "owner_id"),
Index("ix_embeddings_model_dimensions_owner", "model", "dimensions", "owner_id"),
)
class EmbeddingModel(Base):
"""Data model for embeddingmodel values."""
__tablename__ = "embedding_models"
model: Mapped[str] = mapped_column(String(128), primary_key=True)
dimensions: Mapped[int] = mapped_column(Integer, nullable=False)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
)
__table_args__ = (
CheckConstraint("dimensions > 0", name="ck_embedding_models_dimensions_positive"),
Index("ux_embedding_models_model_dimensions", "model", "dimensions", unique=True),
)
class Match(Base):
"""Data model for match values."""
__tablename__ = "matches"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
job_id: Mapped[int] = mapped_column(ForeignKey("job_postings.id"), nullable=False)
candidate_id: Mapped[int] = mapped_column(ForeignKey("candidates.id"), nullable=False)
retrieval_score: Mapped[float | None] = mapped_column(Float, nullable=True)
rerank_score: Mapped[float | None] = mapped_column(Float, nullable=True)
final_score: Mapped[float | None] = mapped_column(Float, nullable=True)
reasons_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
interview_pack_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
)
candidate: Mapped["Candidate"] = relationship()
class AsyncTask(Base):
"""Data model for background task tracking."""
__tablename__ = "async_tasks"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
task_type: Mapped[str] = mapped_column(String(128), nullable=False, index=True)
status: Mapped[str] = mapped_column(String(64), nullable=False, default="PENDING", index=True)
input_payload: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
output_payload: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
nullable=False,
)