diff --git a/python/alembic/richie/versions/2026_03_29-removed_ds_table_from_richie_db_c8a794340928.py b/python/alembic/richie/versions/2026_03_29-removed_ds_table_from_richie_db_c8a794340928.py new file mode 100644 index 0000000..86c9539 --- /dev/null +++ b/python/alembic/richie/versions/2026_03_29-removed_ds_table_from_richie_db_c8a794340928.py @@ -0,0 +1,187 @@ +"""removed ds table from richie DB. + +Revision ID: c8a794340928 +Revises: 6b275323f435 +Create Date: 2026-03-29 15:29:23.643146 + +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +from python.orm import RichieBase + +if TYPE_CHECKING: + from collections.abc import Sequence + +# revision identifiers, used by Alembic. +revision: str = "c8a794340928" +down_revision: str | None = "6b275323f435" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + +schema = RichieBase.schema_name + + +def upgrade() -> None: + """Upgrade.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table("vote_record", schema=schema) + op.drop_index(op.f("ix_vote_congress_chamber"), table_name="vote", schema=schema) + op.drop_index(op.f("ix_vote_date"), table_name="vote", schema=schema) + op.drop_index(op.f("ix_legislator_bioguide_id"), table_name="legislator", schema=schema) + op.drop_table("legislator", schema=schema) + op.drop_table("vote", schema=schema) + op.drop_index(op.f("ix_bill_congress"), table_name="bill", schema=schema) + op.drop_table("bill", schema=schema) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "vote", + sa.Column("congress", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("chamber", sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column("session", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("number", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("vote_type", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("question", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("result", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("result_text", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("vote_date", sa.DATE(), autoincrement=False, nullable=False), + sa.Column("yea_count", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("nay_count", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("not_voting_count", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("present_count", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("bill_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column( + "created", + postgresql.TIMESTAMP(timezone=True), + server_default=sa.text("now()"), + autoincrement=False, + nullable=False, + ), + sa.Column( + "updated", + postgresql.TIMESTAMP(timezone=True), + server_default=sa.text("now()"), + autoincrement=False, + nullable=False, + ), + sa.ForeignKeyConstraint(["bill_id"], [f"{schema}.bill.id"], name=op.f("fk_vote_bill_id_bill")), + sa.PrimaryKeyConstraint("id", name=op.f("pk_vote")), + sa.UniqueConstraint( + "congress", + "chamber", + "session", + "number", + name=op.f("uq_vote_congress_chamber_session_number"), + postgresql_include=[], + postgresql_nulls_not_distinct=False, + ), + schema=schema, + ) + op.create_index(op.f("ix_vote_date"), "vote", ["vote_date"], unique=False, schema=schema) + op.create_index(op.f("ix_vote_congress_chamber"), "vote", ["congress", "chamber"], unique=False, schema=schema) + op.create_table( + "vote_record", + sa.Column("vote_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("legislator_id", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("position", sa.VARCHAR(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint( + ["legislator_id"], + [f"{schema}.legislator.id"], + name=op.f("fk_vote_record_legislator_id_legislator"), + ondelete="CASCADE", + ), + sa.ForeignKeyConstraint( + ["vote_id"], [f"{schema}.vote.id"], name=op.f("fk_vote_record_vote_id_vote"), ondelete="CASCADE" + ), + sa.PrimaryKeyConstraint("vote_id", "legislator_id", name=op.f("pk_vote_record")), + schema=schema, + ) + op.create_table( + "legislator", + sa.Column("bioguide_id", sa.TEXT(), autoincrement=False, nullable=False), + sa.Column("thomas_id", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("lis_id", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("govtrack_id", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("opensecrets_id", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("fec_ids", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("first_name", sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column("last_name", sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column("official_full_name", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("nickname", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("birthday", sa.DATE(), autoincrement=False, nullable=True), + sa.Column("gender", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("current_party", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("current_state", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("current_district", sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column("current_chamber", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column( + "created", + postgresql.TIMESTAMP(timezone=True), + server_default=sa.text("now()"), + autoincrement=False, + nullable=False, + ), + sa.Column( + "updated", + postgresql.TIMESTAMP(timezone=True), + server_default=sa.text("now()"), + autoincrement=False, + nullable=False, + ), + sa.PrimaryKeyConstraint("id", name=op.f("pk_legislator")), + schema=schema, + ) + op.create_index(op.f("ix_legislator_bioguide_id"), "legislator", ["bioguide_id"], unique=True, schema=schema) + op.create_table( + "bill", + sa.Column("congress", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("bill_type", sa.VARCHAR(), autoincrement=False, nullable=False), + sa.Column("number", sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column("title", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("title_short", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("official_title", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("status", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("status_at", sa.DATE(), autoincrement=False, nullable=True), + sa.Column("sponsor_bioguide_id", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("subjects_top_term", sa.VARCHAR(), autoincrement=False, nullable=True), + sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column( + "created", + postgresql.TIMESTAMP(timezone=True), + server_default=sa.text("now()"), + autoincrement=False, + nullable=False, + ), + sa.Column( + "updated", + postgresql.TIMESTAMP(timezone=True), + server_default=sa.text("now()"), + autoincrement=False, + nullable=False, + ), + sa.PrimaryKeyConstraint("id", name=op.f("pk_bill")), + sa.UniqueConstraint( + "congress", + "bill_type", + "number", + name=op.f("uq_bill_congress_type_number"), + postgresql_include=[], + postgresql_nulls_not_distinct=False, + ), + schema=schema, + ) + op.create_index(op.f("ix_bill_congress"), "bill", ["congress"], unique=False, schema=schema) + # ### end Alembic commands ### diff --git a/python/orm/richie/__init__.py b/python/orm/richie/__init__.py index 7be641a..ea7569f 100644 --- a/python/orm/richie/__init__.py +++ b/python/orm/richie/__init__.py @@ -3,7 +3,6 @@ from __future__ import annotations from python.orm.richie.base import RichieBase, TableBase, TableBaseBig, TableBaseSmall -from python.orm.richie.congress import Bill, Legislator, Vote, VoteRecord from python.orm.richie.contact import ( Contact, ContactNeed, @@ -13,17 +12,13 @@ from python.orm.richie.contact import ( ) __all__ = [ - "Bill", "Contact", "ContactNeed", "ContactRelationship", - "Legislator", "Need", "RelationshipType", "RichieBase", "TableBase", "TableBaseBig", "TableBaseSmall", - "Vote", - "VoteRecord", ] diff --git a/python/orm/richie/congress.py b/python/orm/richie/congress.py deleted file mode 100644 index 0a23b20..0000000 --- a/python/orm/richie/congress.py +++ /dev/null @@ -1,150 +0,0 @@ -"""Congress Tracker database models.""" - -from __future__ import annotations - -from datetime import date - -from sqlalchemy import ForeignKey, Index, Text, UniqueConstraint -from sqlalchemy.orm import Mapped, mapped_column, relationship - -from python.orm.richie.base import RichieBase, TableBase - - -class Legislator(TableBase): - """Legislator model - members of Congress.""" - - __tablename__ = "legislator" - - # Natural key - bioguide ID is the authoritative identifier - bioguide_id: Mapped[str] = mapped_column(Text, unique=True, index=True) - - # Other IDs for cross-referencing - thomas_id: Mapped[str | None] - lis_id: Mapped[str | None] - govtrack_id: Mapped[int | None] - opensecrets_id: Mapped[str | None] - fec_ids: Mapped[str | None] # JSON array stored as string - - # Name info - first_name: Mapped[str] - last_name: Mapped[str] - official_full_name: Mapped[str | None] - nickname: Mapped[str | None] - - # Bio - birthday: Mapped[date | None] - gender: Mapped[str | None] # M/F - - # Current term info (denormalized for query efficiency) - current_party: Mapped[str | None] - current_state: Mapped[str | None] - current_district: Mapped[int | None] # House only - current_chamber: Mapped[str | None] # rep/sen - - # Relationships - vote_records: Mapped[list[VoteRecord]] = relationship( - "VoteRecord", - back_populates="legislator", - cascade="all, delete-orphan", - ) - - -class Bill(TableBase): - """Bill model - legislation introduced in Congress.""" - - __tablename__ = "bill" - - # Composite natural key: congress + bill_type + number - congress: Mapped[int] - bill_type: Mapped[str] # hr, s, hres, sres, hjres, sjres - number: Mapped[int] - - # Bill info - title: Mapped[str | None] - title_short: Mapped[str | None] - official_title: Mapped[str | None] - - # Status - status: Mapped[str | None] - status_at: Mapped[date | None] - - # Sponsor - sponsor_bioguide_id: Mapped[str | None] - - # Subjects - subjects_top_term: Mapped[str | None] - - # Relationships - votes: Mapped[list[Vote]] = relationship( - "Vote", - back_populates="bill", - ) - - __table_args__ = ( - UniqueConstraint("congress", "bill_type", "number", name="uq_bill_congress_type_number"), - Index("ix_bill_congress", "congress"), - ) - - -class Vote(TableBase): - """Vote model - roll call votes in Congress.""" - - __tablename__ = "vote" - - # Composite natural key: congress + chamber + session + number - congress: Mapped[int] - chamber: Mapped[str] # house/senate - session: Mapped[int] - number: Mapped[int] - - # Vote details - vote_type: Mapped[str | None] - question: Mapped[str | None] - result: Mapped[str | None] - result_text: Mapped[str | None] - - # Timing - vote_date: Mapped[date] - - # Vote counts (denormalized for efficiency) - yea_count: Mapped[int | None] - nay_count: Mapped[int | None] - not_voting_count: Mapped[int | None] - present_count: Mapped[int | None] - - # Related bill (optional - not all votes are on bills) - bill_id: Mapped[int | None] = mapped_column(ForeignKey("main.bill.id")) - - # Relationships - bill: Mapped[Bill | None] = relationship("Bill", back_populates="votes") - vote_records: Mapped[list[VoteRecord]] = relationship( - "VoteRecord", - back_populates="vote", - cascade="all, delete-orphan", - ) - - __table_args__ = ( - UniqueConstraint("congress", "chamber", "session", "number", name="uq_vote_congress_chamber_session_number"), - Index("ix_vote_date", "vote_date"), - Index("ix_vote_congress_chamber", "congress", "chamber"), - ) - - -class VoteRecord(RichieBase): - """Association table: Vote <-> Legislator with position.""" - - __tablename__ = "vote_record" - - vote_id: Mapped[int] = mapped_column( - ForeignKey("main.vote.id", ondelete="CASCADE"), - primary_key=True, - ) - legislator_id: Mapped[int] = mapped_column( - ForeignKey("main.legislator.id", ondelete="CASCADE"), - primary_key=True, - ) - position: Mapped[str] # Yea, Nay, Not Voting, Present - - # Relationships - vote: Mapped[Vote] = relationship("Vote", back_populates="vote_records") - legislator: Mapped[Legislator] = relationship("Legislator", back_populates="vote_records")