Skip to content

Commit

Permalink
[Issue #1363] Update the Opportunity summary database models based on…
Browse files Browse the repository at this point in the history
… updated database schema plan (#1402)

## Summary
Fixes #1363

### Time to review: __10 mins__

## Changes proposed
Updated the DB models for the opportunity tables

Update the factories to handle creating a current opportunity summary in
a few scenarios

Temporarily disable some validations in the API tests (To be fixed in
#1364 )

## Context for reviewers

https://app.gitbook.com/o/cFcvhi6d0nlLyH2VzVgn/s/v1V0jIH7mb7Yb3jlNrgk/engineering/learnings/opportunity-endpoint-data-model#overview
provides most of the details regarding the updated schema, but in short,
opportunity summary was adjusted to have its own primary key and allow
for multiple opportunity summaries per opportunity - as well as some
shuffling of fields.

There are two migrations in this PR, one to first delete the opportunity
summary table, and the other to add/modify all of the other tables.
Because we changed the primary key and how the connections between the
tables work, Alembic couldn't automatically detect the changes necessary
for creating the tables. While this could be modified manually, it ends
up much cleaner / simpler to just drop and remake the table entirely
instead. Non-locally we've not populated these tables so this has no
impact.



## Additional information
Running the `db-seed-local` script generates data locally as expected:
![Screenshot 2024-03-05 at 1 50 00
PM](https://github.com/HHS/simpler-grants-gov/assets/46358556/fd104e3b-39d8-4987-83d5-03227cc4f819)

In the current table, only 25 records are created as 5 opportunities
have no summary:
![Screenshot 2024-03-05 at 1 50 57
PM](https://github.com/HHS/simpler-grants-gov/assets/46358556/97d0521c-c978-4480-b93b-9b8a2567bc28)

The factories generate the opportunity summary with varying information,
setting certain fields depending on the scenario (eg. only setting
forecasted fields for forecasts):
![Screenshot 2024-03-05 at 1 51 59
PM](https://github.com/HHS/simpler-grants-gov/assets/46358556/b8c8bf92-924b-4128-98f7-aa8d61773e6e)

---------

Co-authored-by: nava-platform-bot <platform-admins@navapbc.com>
  • Loading branch information
chouinar and nava-platform-bot authored Mar 7, 2024
1 parent 5ab44c2 commit f72d63b
Show file tree
Hide file tree
Showing 7 changed files with 971 additions and 119 deletions.
299 changes: 299 additions & 0 deletions api/src/db/migrations/versions/2024_03_07_drop_tables_to_remake.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
"""Drop tables to remake
Revision ID: ac80e949bcf8
Revises: 5d58c38f2cac
Create Date: 2024-03-07 10:20:15.639825
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "ac80e949bcf8"
down_revision = "5d58c38f2cac"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("link_funding_instrument_opportunity")
op.drop_index("opportunity_is_draft_idx", table_name="opportunity")
op.drop_index("opportunity_opportunity_category_id_idx", table_name="opportunity")
op.drop_index("opportunity_opportunity_title_idx", table_name="opportunity")

op.drop_table("link_funding_category_opportunity")
op.drop_table("link_applicant_type_opportunity")
op.drop_index(
"opportunity_assistance_listing_opportunity_id_idx",
table_name="opportunity_assistance_listing",
)
op.drop_table("opportunity_assistance_listing")
op.drop_table("opportunity_summary")
op.drop_table("opportunity")
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"opportunity",
sa.Column(
"opportunity_id",
sa.INTEGER(),
server_default=sa.text("nextval('opportunity_opportunity_id_seq'::regclass)"),
autoincrement=True,
nullable=False,
),
sa.Column("opportunity_number", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("opportunity_title", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("agency", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("is_draft", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column(
"created_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.Column(
"updated_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.Column("category_explanation", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("revision_number", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("modified_comments", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("publisher_user_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("publisher_profile_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("opportunity_category_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
["opportunity_category_id"],
["lk_opportunity_category.opportunity_category_id"],
name="opportunity_opportunity_category_id_lk_opportunity_cate_c6e9",
),
sa.PrimaryKeyConstraint("opportunity_id", name="opportunity_pkey"),
postgresql_ignore_search_path=False,
)
op.create_index(
"opportunity_opportunity_title_idx", "opportunity", ["opportunity_title"], unique=False
)
op.create_index(
"opportunity_opportunity_category_id_idx",
"opportunity",
["opportunity_category_id"],
unique=False,
)
op.create_index("opportunity_is_draft_idx", "opportunity", ["is_draft"], unique=False)
op.create_table(
"opportunity_summary",
sa.Column("opportunity_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("opportunity_status_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("summary_description", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("is_cost_sharing", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("close_date", sa.DATE(), autoincrement=False, nullable=True),
sa.Column("close_date_description", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("post_date", sa.DATE(), autoincrement=False, nullable=True),
sa.Column("archive_date", sa.DATE(), autoincrement=False, nullable=True),
sa.Column("unarchive_date", sa.DATE(), autoincrement=False, nullable=True),
sa.Column("expected_number_of_awards", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"estimated_total_program_funding", sa.INTEGER(), autoincrement=False, nullable=True
),
sa.Column("award_floor", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("award_ceiling", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("additional_info_url", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("additional_info_url_description", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("version_number", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("modification_comments", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("funding_category_description", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"applicant_eligibility_description", sa.TEXT(), autoincrement=False, nullable=True
),
sa.Column("agency_code", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("agency_name", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("agency_phone_number", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("agency_contact_description", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("agency_email_address", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"agency_email_address_description", sa.TEXT(), autoincrement=False, nullable=True
),
sa.Column("can_send_mail", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("publisher_profile_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("publisher_user_id", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("updated_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("created_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"created_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.Column(
"updated_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.ForeignKeyConstraint(
["opportunity_id"],
["opportunity.opportunity_id"],
name="opportunity_summary_opportunity_id_opportunity_fkey",
),
sa.ForeignKeyConstraint(
["opportunity_status_id"],
["lk_opportunity_status.opportunity_status_id"],
name="opportunity_summary_opportunity_status_id_lk_opportunit_ea00",
),
sa.PrimaryKeyConstraint("opportunity_id", name="opportunity_summary_pkey"),
)
op.create_table(
"opportunity_assistance_listing",
sa.Column(
"opportunity_assistance_listing_id", sa.INTEGER(), autoincrement=True, nullable=False
),
sa.Column("opportunity_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("program_title", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("assistance_listing_number", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("updated_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("created_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"created_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.Column(
"updated_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.ForeignKeyConstraint(
["opportunity_id"],
["opportunity.opportunity_id"],
name="opportunity_assistance_listing_opportunity_id_opportunity_fkey",
),
sa.PrimaryKeyConstraint(
"opportunity_assistance_listing_id", name="opportunity_assistance_listing_pkey"
),
)
op.create_index(
"opportunity_assistance_listing_opportunity_id_idx",
"opportunity_assistance_listing",
["opportunity_id"],
unique=False,
)
op.create_table(
"link_applicant_type_opportunity",
sa.Column("opportunity_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("applicant_type_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("updated_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("created_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"created_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.Column(
"updated_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.ForeignKeyConstraint(
["applicant_type_id"],
["lk_applicant_type.applicant_type_id"],
name="link_applicant_type_opportunity_applicant_type_id_lk_ap_7903",
),
sa.ForeignKeyConstraint(
["opportunity_id"],
["opportunity.opportunity_id"],
name="link_applicant_type_opportunity_opportunity_id_opportunity_fkey",
),
sa.PrimaryKeyConstraint(
"opportunity_id", "applicant_type_id", name="link_applicant_type_opportunity_pkey"
),
)
op.create_table(
"link_funding_category_opportunity",
sa.Column("opportunity_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("funding_category_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("updated_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("created_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"created_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.Column(
"updated_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.ForeignKeyConstraint(
["funding_category_id"],
["lk_funding_category.funding_category_id"],
name="link_funding_category_opportunity_funding_category_id_l_4add",
),
sa.ForeignKeyConstraint(
["opportunity_id"],
["opportunity.opportunity_id"],
name="link_funding_category_opportunity_opportunity_id_opport_eb65",
),
sa.PrimaryKeyConstraint(
"opportunity_id", "funding_category_id", name="link_funding_category_opportunity_pkey"
),
)

op.create_table(
"link_funding_instrument_opportunity",
sa.Column("opportunity_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("funding_instrument_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("updated_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("created_by", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"created_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.Column(
"updated_at",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.ForeignKeyConstraint(
["funding_instrument_id"],
["lk_funding_instrument.funding_instrument_id"],
name="link_funding_instrument_opportunity_funding_instrument__68d6",
),
sa.ForeignKeyConstraint(
["opportunity_id"],
["opportunity.opportunity_id"],
name="link_funding_instrument_opportunity_opportunity_id_oppo_9420",
),
sa.PrimaryKeyConstraint(
"opportunity_id",
"funding_instrument_id",
name="link_funding_instrument_opportunity_pkey",
),
)
# ### end Alembic commands ###
Loading

0 comments on commit f72d63b

Please sign in to comment.