"""Company-wide Announcement request ORM model. The Feishu template (flow_key=announcement_request) has a single required paragraph field — Application description. On approval IT publishes the announcement in the company channel; there is no ongoing privilege to revoke afterwards, so the lifecycle is just pending → approved / rejected / cancelled. """ from __future__ import annotations import uuid from datetime import datetime from sqlalchemy import DateTime, ForeignKey, String, Text, func from sqlalchemy.orm import Mapped, mapped_column from app.core.database import Base ANNOUNCEMENT_REQ_STATUS_PENDING = "pending" ANNOUNCEMENT_REQ_STATUS_APPROVED = "approved" ANNOUNCEMENT_REQ_STATUS_REJECTED = "rejected" ANNOUNCEMENT_REQ_STATUS_CANCELLED = "cancelled" class AnnouncementRequest(Base): __tablename__ = "announcement_requests" id: Mapped[str] = mapped_column( String(36), primary_key=True, default=lambda: str(uuid.uuid4()), ) person_id: Mapped[str] = mapped_column( String(36), ForeignKey("identity_persons.id"), nullable=False, ) description: Mapped[str] = mapped_column(Text, nullable=False) status: Mapped[str] = mapped_column( String(32), nullable=False, default=ANNOUNCEMENT_REQ_STATUS_PENDING, ) feishu_instance_code: Mapped[str | None] = mapped_column( String(64), nullable=True, ) approval_request_id: Mapped[str | None] = mapped_column( String(36), ForeignKey("approval_requests.id", ondelete="SET NULL"), nullable=True, ) granted_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, ) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False, ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False, )