Files

128 lines
3.7 KiB
Python

"""SQLModel table definitions for Ten31Portal."""
import enum
from datetime import date, datetime
from decimal import Decimal
from typing import Optional
from sqlmodel import Field, SQLModel, Column, String, JSON, UniqueConstraint
# --- Enums ---
class UserRole(str, enum.Enum):
approver = "approver"
cfo = "cfo"
fund_admin = "fund_admin"
viewer = "viewer"
class EntityType(str, enum.Enum):
fund = "fund"
spv = "spv"
gp = "gp"
mgmt_co = "mgmt_co"
class EntityStatus(str, enum.Enum):
active = "active"
closed = "closed"
class RoundStatus(str, enum.Enum):
draft = "draft"
submitted = "submitted"
approved = "approved"
returned = "returned"
# --- Tables ---
class User(SQLModel, table=True):
__tablename__ = "users"
id: int | None = Field(default=None, primary_key=True)
name: str
email: str = Field(sa_column=Column(String, unique=True, nullable=False))
password_hash: str
role: UserRole
is_active: bool = Field(default=True)
created_at: datetime = Field(default_factory=datetime.utcnow)
class Entity(SQLModel, table=True):
__tablename__ = "entities"
id: int | None = Field(default=None, primary_key=True)
name: str
type: EntityType
vintage_year: int | None = None
fund_size_cents: int | None = None
status: EntityStatus = Field(default=EntityStatus.active)
created_at: datetime = Field(default_factory=datetime.utcnow)
class Holding(SQLModel, table=True):
__tablename__ = "holdings"
id: int | None = Field(default=None, primary_key=True)
entity_id: int = Field(foreign_key="entities.id")
company_name: str
created_at: datetime = Field(default_factory=datetime.utcnow)
class Position(SQLModel, table=True):
__tablename__ = "positions"
id: int | None = Field(default=None, primary_key=True)
holding_id: int = Field(foreign_key="holdings.id")
security_name: str
investment_date: date
shares: str | None = None # Decimal stored as string
cost_cents: int
created_at: datetime = Field(default_factory=datetime.utcnow)
class ValuationRound(SQLModel, table=True):
__tablename__ = "valuation_rounds"
__table_args__ = (
UniqueConstraint("entity_id", "quarter_end", name="uq_round_entity_quarter"),
)
id: int | None = Field(default=None, primary_key=True)
entity_id: int = Field(foreign_key="entities.id")
quarter_end: date
status: RoundStatus = Field(default=RoundStatus.draft)
submitted_by: int | None = Field(default=None, foreign_key="users.id")
submitted_at: datetime | None = None
approved_by: int | None = Field(default=None, foreign_key="users.id")
approved_at: datetime | None = None
return_note: str | None = None
is_seed: bool = Field(default=False)
created_at: datetime = Field(default_factory=datetime.utcnow)
class Valuation(SQLModel, table=True):
__tablename__ = "valuations"
__table_args__ = (
UniqueConstraint("round_id", "position_id", name="uq_valuation_round_position"),
)
id: int | None = Field(default=None, primary_key=True)
round_id: int = Field(foreign_key="valuation_rounds.id")
position_id: int = Field(foreign_key="positions.id")
value_cents: int
created_at: datetime = Field(default_factory=datetime.utcnow)
class AuditLog(SQLModel, table=True):
__tablename__ = "audit_log"
id: int | None = Field(default=None, primary_key=True)
actor_user_id: int | None = Field(default=None, foreign_key="users.id")
action: str
object_type: str
object_id: int | None = None
detail: str | None = Field(default=None, sa_column=Column(JSON, nullable=True))
created_at: datetime = Field(default_factory=datetime.utcnow)