Coverage for polar/models/organization_review.py: 92%
37 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 12:42 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 12:42 +0000
1from datetime import datetime
2from enum import StrEnum
3from typing import TYPE_CHECKING, Any
4from uuid import UUID
6from sqlalchemy import TIMESTAMP, ForeignKey, String, Text, Uuid
7from sqlalchemy.dialects.postgresql import JSONB
8from sqlalchemy.orm import Mapped, declared_attr, mapped_column, relationship
10from polar.kit.db.models import RecordModel
12if TYPE_CHECKING: 12 ↛ 13line 12 didn't jump to line 13 because the condition on line 12 was never true
13 from polar.models.organization import Organization
16class OrganizationReview(RecordModel):
17 """Model to store AI validation responses for organizations."""
19 class Verdict(StrEnum):
20 PASS = "PASS"
21 FAIL = "FAIL"
22 UNCERTAIN = "UNCERTAIN"
24 class AppealDecision(StrEnum):
25 APPROVED = "approved"
26 REJECTED = "rejected"
28 __tablename__ = "organization_reviews"
30 organization_id: Mapped[UUID] = mapped_column(
31 Uuid,
32 ForeignKey("organizations.id", ondelete="cascade"),
33 nullable=False,
34 unique=True,
35 index=True,
36 )
38 verdict: Mapped[Verdict] = mapped_column(String, nullable=False)
39 risk_score: Mapped[float] = mapped_column(nullable=False)
40 violated_sections: Mapped[list[str]] = mapped_column(
41 JSONB, nullable=False, default=list
42 )
43 reason: Mapped[str] = mapped_column(Text, nullable=False)
45 timed_out: Mapped[bool] = mapped_column(nullable=False, default=False)
46 model_used: Mapped[str] = mapped_column(String, nullable=False)
48 organization_details_snapshot: Mapped[dict[str, Any]] = mapped_column(
49 JSONB, nullable=False, default=dict
50 )
52 validated_at: Mapped[datetime] = mapped_column(
53 TIMESTAMP(timezone=True), nullable=False, default=lambda: datetime.now()
54 )
56 # Appeal fields
57 appeal_submitted_at: Mapped[datetime | None] = mapped_column(
58 TIMESTAMP(timezone=True), nullable=True, default=None
59 )
60 appeal_reason: Mapped[str | None] = mapped_column(Text, nullable=True, default=None)
61 appeal_reviewed_at: Mapped[datetime | None] = mapped_column(
62 TIMESTAMP(timezone=True), nullable=True, default=None
63 )
64 appeal_decision: Mapped[AppealDecision | None] = mapped_column(
65 String, nullable=True, default=None
66 )
68 @declared_attr
69 def organization(cls) -> Mapped["Organization"]:
70 return relationship("Organization", lazy="raise", back_populates="review")
72 def __repr__(self) -> str:
73 return f"OrganizationReview(id={self.id}, organization_id={self.organization_id}, verdict={self.verdict})"