"""Contract model.""" import enum from datetime import date, datetime from typing import Optional from sqlalchemy import String, Text, Date, DateTime, Enum as SQLEnum, Integer, ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from app.core.database import Base class ContractStatus(str, enum.Enum): """Contract status enumeration.""" DRAFT = "draft" PENDING_APPROVAL = "pending_approval" APPROVED = "approved" PENDING_SIGNATURE = "pending_signature" SIGNED = "signed" ARCHIVED = "archived" REJECTED = "rejected" class Contract(Base): """Contract model.""" __tablename__ = "contracts" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) template_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("contract_templates.id"), nullable=True) title: Mapped[str] = mapped_column(String(200), index=True) contract_number: Mapped[Optional[str]] = mapped_column(String(50), nullable=True) party_a: Mapped[str] = mapped_column(String(100)) party_b: Mapped[str] = mapped_column(String(100)) content: Mapped[str] = mapped_column(Text) status: Mapped[ContractStatus] = mapped_column( SQLEnum(ContractStatus), default=ContractStatus.DRAFT ) effective_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True) expiry_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True) file_path: Mapped[Optional[str]] = mapped_column(String(255), nullable=True) created_by: Mapped[int] = mapped_column(Integer, ForeignKey("users.id")) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) updated_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) def __init__( self, title: str, party_a: str, party_b: str, content: str, created_by: int, template_id: Optional[int] = None, contract_number: Optional[str] = None, status: ContractStatus = ContractStatus.DRAFT, effective_date: Optional[date] = None, expiry_date: Optional[date] = None, file_path: Optional[str] = None, **kwargs ): self.title = title self.party_a = party_a self.party_b = party_b self.content = content self.created_by = created_by self.template_id = template_id self.contract_number = contract_number self.status = status self.effective_date = effective_date self.expiry_date = expiry_date self.file_path = file_path self.created_at = datetime.utcnow() self.updated_at = datetime.utcnow() class ContractTemplate(Base): """Contract template model.""" __tablename__ = "contract_templates" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(String(100)) contract_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True) content: Mapped[str] = mapped_column(Text) variables: Mapped[Optional[dict]] = mapped_column(String, nullable=True) # JSON string created_by: Mapped[int] = mapped_column(Integer, ForeignKey("users.id")) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) def __init__( self, name: str, content: str, created_by: int, contract_type: Optional[str] = None, variables: Optional[dict] = None, **kwargs ): self.name = name self.content = content self.created_by = created_by self.contract_type = contract_type self.variables = variables self.created_at = datetime.utcnow() class ContractApproval(Base): """Contract approval model.""" __tablename__ = "contract_approvals" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) contract_id: Mapped[int] = mapped_column(Integer, ForeignKey("contracts.id"), index=True) approver_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), index=True) status: Mapped[ContractStatus] = mapped_column(SQLEnum(ContractStatus)) comment: Mapped[Optional[str]] = mapped_column(Text, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False) approved_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) def __init__( self, contract_id: int, approver_id: int, status: ContractStatus, comment: Optional[str] = None, **kwargs ): self.contract_id = contract_id self.approver_id = approver_id self.status = status self.comment = comment self.created_at = datetime.utcnow()