File size: 4,130 Bytes
57303cc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""
models.py — SQLAlchemy ORM models.

Defines the four core tables: Client, Candidate, Score, and Feedback.
"""

import enum
from datetime import datetime, timezone

from sqlalchemy import (
    Column,
    DateTime,
    Enum,
    Float,
    ForeignKey,
    Integer,
    String,
    Text,
)
from sqlalchemy.orm import relationship

from .database import Base


# ---------------------------------------------------------------------------
# Enums
# ---------------------------------------------------------------------------
class ArchetypeEnum(str, enum.Enum):
    """Client cultural archetype."""
    consulting = "consulting"
    startup = "startup"


class OutcomeEnum(str, enum.Enum):
    """Post-interview outcome."""
    accepted = "accepted"
    rejected = "rejected"


class ReasonEnum(str, enum.Enum):
    """Primary reason for the interview decision."""
    communication_soft_skills = "communication_soft_skills"
    technical_capability = "technical_capability"
    alignment_cultural_vibe = "alignment_cultural_vibe"
    candidate_declined = "candidate_declined"


# ---------------------------------------------------------------------------
# ORM Models
# ---------------------------------------------------------------------------
class Client(Base):
    """A client company profile with archetype and minimum BARS thresholds."""

    __tablename__ = "clients"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(255), nullable=False)
    archetype = Column(Enum(ArchetypeEnum), nullable=False)
    expectations = Column(Text, default="")

    # Minimum acceptable BARS scores per competency (1-5)
    min_communication = Column(Integer, default=3)
    min_adaptability = Column(Integer, default=3)
    min_collaboration = Column(Integer, default=3)
    min_problem_solving = Column(Integer, default=3)
    min_leadership = Column(Integer, default=3)

    created_at = Column(
        DateTime, default=lambda: datetime.now(timezone.utc)
    )

    candidates = relationship("Candidate", back_populates="client")


class Candidate(Base):
    """A candidate being evaluated for a specific client."""

    __tablename__ = "candidates"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(255), nullable=False)
    email = Column(String(255), default="")
    recruiter_notes = Column(Text, default="")
    client_id = Column(Integer, ForeignKey("clients.id"), nullable=False)
    created_at = Column(
        DateTime, default=lambda: datetime.now(timezone.utc)
    )

    client = relationship("Client", back_populates="candidates")
    score = relationship(
        "Score", back_populates="candidate", uselist=False
    )
    feedback = relationship(
        "Feedback", back_populates="candidate", uselist=False
    )


class Score(Base):
    """BARS competency scores for a candidate (1-5 per dimension)."""

    __tablename__ = "scores"

    id = Column(Integer, primary_key=True, index=True)
    candidate_id = Column(
        Integer, ForeignKey("candidates.id"), unique=True, nullable=False
    )

    communication = Column(Integer, nullable=False)
    adaptability = Column(Integer, nullable=False)
    collaboration = Column(Integer, nullable=False)
    problem_solving = Column(Integer, nullable=False)
    leadership = Column(Integer, nullable=False)

    overall_match = Column(Float, default=0.0)
    mismatches = Column(Text, default="[]")  # JSON-encoded list of strings

    candidate = relationship("Candidate", back_populates="score")


class Feedback(Base):
    """Post-interview outcome and client feedback."""

    __tablename__ = "feedbacks"

    id = Column(Integer, primary_key=True, index=True)
    candidate_id = Column(
        Integer, ForeignKey("candidates.id"), unique=True, nullable=False
    )

    outcome = Column(Enum(OutcomeEnum), nullable=False)
    primary_reason = Column(Enum(ReasonEnum), nullable=False)
    client_notes = Column(Text, default="")
    created_at = Column(
        DateTime, default=lambda: datetime.now(timezone.utc)
    )

    candidate = relationship("Candidate", back_populates="feedback")