owenkaplinsky's picture
update from github stable code (#3)
3370983 verified
raw
history blame
5.56 kB
from sqlalchemy import (
Column, String, Integer, Float, Enum, DateTime, Text, ForeignKey, JSON
)
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import declarative_base, relationship
from datetime import datetime
import enum
import uuid
Base = declarative_base()
# ==============================================================
# ENUM DEFINITIONS
# ==============================================================
class CandidateStatus(enum.Enum):
APPLIED = "applied"
CV_SCREENED = "cv_screened"
INVITED_VOICE = "invited_voice"
VOICE_DONE = "voice_done"
SCHEDULED_HR = "scheduled_hr"
DECISION_PENDING = "decision_pending"
REJECTED = "rejected"
HIRED = "hired"
class InterviewStatus(enum.Enum):
SCHEDULED = "scheduled"
COMPLETED = "completed"
CANCELLED = "cancelled"
class Decision(enum.Enum):
HIRE = "hire"
REJECT = "reject"
MAYBE = "maybe"
# ==============================================================
# MAIN TABLES
# ==============================================================
class Candidate(Base):
__tablename__ = "candidates"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
full_name = Column(String(255), nullable=False)
email = Column(String(255), nullable=False, unique=True)
phone_number = Column(String(50), nullable=True)
cv_file_path = Column(String(500), nullable=True)
parsed_cv_json = Column(JSON, nullable=True)
status = Column(Enum(CandidateStatus), default=CandidateStatus.APPLIED)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
cv_results = relationship("CVScreeningResult", back_populates="candidate", cascade="all, delete-orphan")
voice_results = relationship("VoiceScreeningResult", back_populates="candidate", cascade="all, delete-orphan")
interviews = relationship("InterviewScheduling", back_populates="candidate", cascade="all, delete-orphan")
decision = relationship("FinalDecision", back_populates="candidate", uselist=False, cascade="all, delete-orphan")
# ==============================================================
# CV SCREENING RESULTS
# ==============================================================
class CVScreeningResult(Base):
__tablename__ = "cv_screening_results"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
candidate_id = Column(UUID(as_uuid=True), ForeignKey("candidates.id"), nullable=False)
job_title = Column(String(255), nullable=True)
skills_match_score = Column(Float, nullable=True)
experience_match_score = Column(Float, nullable=True)
education_match_score = Column(Float, nullable=True)
overall_fit_score = Column(Float, nullable=True)
llm_feedback = Column(Text, nullable=True)
reasoning_trace = Column(JSON, nullable=True)
timestamp = Column(DateTime, default=datetime.utcnow)
candidate = relationship("Candidate", back_populates="cv_results")
# ==============================================================
# VOICE SCREENING RESULTS
# ==============================================================
class VoiceScreeningResult(Base):
__tablename__ = "voice_screening_results"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
candidate_id = Column(UUID(as_uuid=True), ForeignKey("candidates.id"), nullable=False)
call_sid = Column(String(255), nullable=True)
transcript_text = Column(Text, nullable=True)
sentiment_score = Column(Float, nullable=True)
confidence_score = Column(Float, nullable=True)
communication_score = Column(Float, nullable=True)
llm_summary = Column(Text, nullable=True)
llm_judgment_json = Column(JSON, nullable=True)
audio_url = Column(String(500), nullable=True)
timestamp = Column(DateTime, default=datetime.utcnow)
candidate = relationship("Candidate", back_populates="voice_results")
# ==============================================================
# INTERVIEW SCHEDULING
# ==============================================================
class InterviewScheduling(Base):
__tablename__ = "interview_scheduling"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
candidate_id = Column(UUID(as_uuid=True), ForeignKey("candidates.id"), nullable=False)
calendar_event_id = Column(String(255), nullable=True)
event_summary = Column(String(255), nullable=True)
start_time = Column(DateTime, nullable=True)
end_time = Column(DateTime, nullable=True)
status = Column(Enum(InterviewStatus), default=InterviewStatus.SCHEDULED)
timestamp = Column(DateTime, default=datetime.utcnow)
candidate = relationship("Candidate", back_populates="interviews")
# ==============================================================
# FINAL DECISION
# ==============================================================
class FinalDecision(Base):
__tablename__ = "final_decision"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
candidate_id = Column(UUID(as_uuid=True), ForeignKey("candidates.id"), nullable=False, unique=True)
overall_score = Column(Float, nullable=True)
decision = Column(Enum(Decision), default=Decision.MAYBE)
llm_rationale = Column(Text, nullable=True)
human_notes = Column(Text, nullable=True)
timestamp = Column(DateTime, default=datetime.utcnow)
candidate = relationship("Candidate", back_populates="decision")