"""Amendment models and official action context.""" from __future__ import annotations from datetime import date, datetime from sqlalchemy import DateTime, ForeignKey, Index, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column, relationship from pipelines.orm.data_science_dev.base import DataScienceDevTableBase class Amendment(DataScienceDevTableBase): """Congressional amendment linked to a bill or to another amendment.""" __tablename__ = "amendment" __table_args__ = ( UniqueConstraint( "congress", "amendment_type", "number", name="uq_amendment_congress_type_number", ), ) congress: Mapped[int] amendment_type: Mapped[str] number: Mapped[int] chamber: Mapped[str] description: Mapped[str | None] purpose: Mapped[str | None] amended_bill_id: Mapped[int | None] = mapped_column( ForeignKey("main.bill.id", ondelete="SET NULL") ) amended_amendment_id: Mapped[int | None] = mapped_column( ForeignKey("main.amendment.id", ondelete="SET NULL") ) source_path: Mapped[str | None] source_artifact_id: Mapped[int | None] = mapped_column( ForeignKey("main.source_artifact.id", ondelete="SET NULL") ) actions: Mapped[list[AmendmentAction]] = relationship( "AmendmentAction", back_populates="amendment", cascade="all, delete-orphan", ) amended_amendment: Mapped[Amendment | None] = relationship( "Amendment", remote_side="Amendment.id", ) class AmendmentAction(DataScienceDevTableBase): """Official action row for an amendment.""" __tablename__ = "amendment_action" __table_args__ = ( UniqueConstraint( "amendment_id", "sequence", name="uq_amendment_action_amendment_id_sequence", ), ) amendment_id: Mapped[int] = mapped_column( ForeignKey("main.amendment.id", ondelete="CASCADE") ) sequence: Mapped[int] action_date: Mapped[date] action_time: Mapped[str | None] action_text: Mapped[str] action_type: Mapped[str | None] action_code: Mapped[str | None] source_system_code: Mapped[str | None] source_system_name: Mapped[str | None] source_artifact_id: Mapped[int | None] = mapped_column( ForeignKey("main.source_artifact.id", ondelete="SET NULL") ) amendment: Mapped[Amendment] = relationship( "Amendment", back_populates="actions", ) recorded_votes: Mapped[list[AmendmentActionRecordedVote]] = relationship( "AmendmentActionRecordedVote", back_populates="amendment_action", cascade="all, delete-orphan", ) class AmendmentActionRecordedVote(DataScienceDevTableBase): """Recorded vote nested under one official amendment action.""" __tablename__ = "amendment_action_recorded_vote" __table_args__ = ( UniqueConstraint( "amendment_action_id", "congress", "chamber", "session_number", "roll_number", name="uq_amendment_action_recorded_vote_match_key", ), Index( "ix_amendment_action_recorded_vote_match_tuple", "congress", "chamber", "session_number", "roll_number", ), ) amendment_action_id: Mapped[int] = mapped_column( ForeignKey("main.amendment_action.id", ondelete="CASCADE") ) congress: Mapped[int] chamber: Mapped[str] session_number: Mapped[int] roll_number: Mapped[int] vote_datetime: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) vote_url: Mapped[str | None] amendment_action: Mapped[AmendmentAction] = relationship( "AmendmentAction", back_populates="recorded_votes", )