Skip to content

Commit

Permalink
[Issue #2123] Add Opportunity Attachment and Lookup Tables (#2483)
Browse files Browse the repository at this point in the history
## Summary
Fixes #2123

### Time to review: 10 mins

## Changes proposed
- Add models and supporting migrations for Opportunity attachments,
including lookup table for type.

## Context for reviewers
See generated migration and screenshots of result after db upgrade. 

Only the created_by, updated_by, and legacy_folder_id columns should be
nullable.

## Additional information
Screenshots of new tables after running `make db-upgrade`

<img width="1060" alt="Screenshot 2024-10-16 at 9 53 59 AM"
src="https://github.com/user-attachments/assets/58e6e8b6-e86f-40b8-a7b3-93524d794456">

<img width="1062" alt="Screenshot 2024-10-16 at 9 53 47 AM"
src="https://github.com/user-attachments/assets/692faac8-eefb-4845-b231-14ad403ddfad">

<img width="874" alt="Screenshot 2024-10-16 at 9 55 06 AM"
src="https://github.com/user-attachments/assets/e877a79e-15cc-4f1a-ac36-fb3fa4526515">

---------

Co-authored-by: Michael Huneke <[email protected]>
Co-authored-by: Michael Chouinard <[email protected]>
Co-authored-by: nava-platform-bot <[email protected]>
  • Loading branch information
4 people authored Oct 17, 2024
1 parent f5862aa commit 1053f0b
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 0 deletions.
5 changes: 5 additions & 0 deletions api/src/constants/lookup_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,8 @@ class AgencySubmissionNotificationSetting(StrEnum):
NEVER = "never"
FIRST_APPLICATION_ONLY = "first_application_only"
ALWAYS = "always"


class OpportunityAttachmentType(StrEnum):
NOTICE_OF_FUNDING_OPPORTUNITY = "notice_of_funding_opportunity"
OTHER = "other"
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""Add opportunity attachment tables
Revision ID: 56448a3ecb8f
Revises: fa38970d0cef
Create Date: 2024-10-16 22:00:42.274537
"""

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "56448a3ecb8f"
down_revision = "fa38970d0cef"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"lk_opportunity_attachment_type",
sa.Column("opportunity_attachment_type_id", sa.Integer(), nullable=False),
sa.Column("description", sa.Text(), nullable=False),
sa.Column(
"created_at",
sa.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
nullable=False,
),
sa.Column(
"updated_at",
sa.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
nullable=False,
),
sa.PrimaryKeyConstraint(
"opportunity_attachment_type_id", name=op.f("lk_opportunity_attachment_type_pkey")
),
schema="api",
)
op.create_table(
"opportunity_attachment",
sa.Column("attachment_id", sa.BigInteger(), nullable=False),
sa.Column("opportunity_id", sa.BigInteger(), nullable=False),
sa.Column("opportunity_attachment_type_id", sa.Integer(), nullable=False),
sa.Column("file_location", sa.Text(), nullable=False),
sa.Column("mime_type", sa.Text(), nullable=False),
sa.Column("file_name", sa.Text(), nullable=False),
sa.Column("file_description", sa.Text(), nullable=False),
sa.Column("file_size_bytes", sa.BigInteger(), nullable=False),
sa.Column("created_by", sa.Text(), nullable=True),
sa.Column("updated_by", sa.Text(), nullable=True),
sa.Column("legacy_folder_id", sa.BigInteger(), nullable=True),
sa.Column(
"created_at",
sa.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
nullable=False,
),
sa.Column(
"updated_at",
sa.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
nullable=False,
),
sa.ForeignKeyConstraint(
["opportunity_attachment_type_id"],
["api.lk_opportunity_attachment_type.opportunity_attachment_type_id"],
name=op.f(
"opportunity_attachment_opportunity_attachment_type_id_lk_opportunity_attachment_type_fkey"
),
),
sa.ForeignKeyConstraint(
["opportunity_id"],
["api.opportunity.opportunity_id"],
name=op.f("opportunity_attachment_opportunity_id_opportunity_fkey"),
),
sa.PrimaryKeyConstraint("attachment_id", name=op.f("opportunity_attachment_pkey")),
schema="api",
)
op.create_index(
op.f("opportunity_attachment_opportunity_attachment_type_id_idx"),
"opportunity_attachment",
["opportunity_attachment_type_id"],
unique=False,
schema="api",
)
op.create_index(
op.f("opportunity_attachment_opportunity_id_idx"),
"opportunity_attachment",
["opportunity_id"],
unique=False,
schema="api",
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(
op.f("opportunity_attachment_opportunity_id_idx"),
table_name="opportunity_attachment",
schema="api",
)
op.drop_index(
op.f("opportunity_attachment_opportunity_attachment_type_id_idx"),
table_name="opportunity_attachment",
schema="api",
)
op.drop_table("opportunity_attachment", schema="api")
op.drop_table("lk_opportunity_attachment_type", schema="api")
# ### end Alembic commands ###
22 changes: 22 additions & 0 deletions api/src/db/models/lookup_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
ApplicantType,
FundingCategory,
FundingInstrument,
OpportunityAttachmentType,
OpportunityCategory,
OpportunityStatus,
)
Expand All @@ -21,6 +22,12 @@
]
)

OPPORTUNITY_ATTACHMENT_TYPE_CONFIG = LookupConfig(
[
LookupStr(OpportunityAttachmentType.NOTICE_OF_FUNDING_OPPORTUNITY, 1),
LookupStr(OpportunityAttachmentType.OTHER, 2),
]
)

OPPORTUNITY_CATEGORY_CONFIG = LookupConfig(
[
Expand Down Expand Up @@ -205,3 +212,18 @@ def from_lookup(cls, lookup: Lookup) -> "LkAgencySubmissionNotificationSetting":
agency_submission_notification_setting_id=lookup.lookup_val,
description=lookup.get_description(),
)


@LookupRegistry.register_lookup(OPPORTUNITY_ATTACHMENT_TYPE_CONFIG)
class LkOpportunityAttachmentType(LookupTable, TimestampMixin):
__tablename__ = "lk_opportunity_attachment_type"

opportunity_attachment_type_id: Mapped[int] = mapped_column(primary_key=True)
description: Mapped[str]

@classmethod
def from_lookup(cls, lookup: Lookup) -> "LkOpportunityAttachmentType":
return LkOpportunityAttachmentType(
opportunity_attachment_type_id=lookup.lookup_val,
description=lookup.get_description(),
)
32 changes: 32 additions & 0 deletions api/src/db/models/opportunity_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ApplicantType,
FundingCategory,
FundingInstrument,
OpportunityAttachmentType,
OpportunityCategory,
OpportunityStatus,
)
Expand All @@ -18,6 +19,7 @@
LkApplicantType,
LkFundingCategory,
LkFundingInstrument,
LkOpportunityAttachmentType,
LkOpportunityCategory,
LkOpportunityStatus,
)
Expand Down Expand Up @@ -51,6 +53,10 @@ class Opportunity(ApiSchemaTable, TimestampMixin):
publisher_user_id: Mapped[str | None]
publisher_profile_id: Mapped[int | None] = mapped_column(BigInteger)

opportunity_attachments: Mapped[list["OpportunityAttachment"]] = relationship(
back_populates="opportunity", uselist=True, cascade="all, delete-orphan"
)

opportunity_assistance_listings: Mapped[list["OpportunityAssistanceListing"]] = relationship(
back_populates="opportunity", uselist=True, cascade="all, delete-orphan"
)
Expand Down Expand Up @@ -385,3 +391,29 @@ class CurrentOpportunitySummary(ApiSchemaTable, TimestampMixin):
ForeignKey(LkOpportunityStatus.opportunity_status_id),
index=True,
)


class OpportunityAttachment(ApiSchemaTable, TimestampMixin):
__tablename__ = "opportunity_attachment"

attachment_id: Mapped[int] = mapped_column(BigInteger, primary_key=True)

opportunity_id: Mapped[int] = mapped_column(
BigInteger, ForeignKey(Opportunity.opportunity_id), index=True
)
opportunity: Mapped[Opportunity] = relationship(single_parent=True)
opportunity_attachment_type: Mapped[OpportunityAttachmentType] = mapped_column(
"opportunity_attachment_type_id",
LookupColumn(LkOpportunityAttachmentType),
ForeignKey(LkOpportunityAttachmentType.opportunity_attachment_type_id),
index=True,
)

file_location: Mapped[str]
mime_type: Mapped[str]
file_name: Mapped[str]
file_description: Mapped[str]
file_size_bytes: Mapped[int] = mapped_column(BigInteger)
created_by: Mapped[str | None]
updated_by: Mapped[str | None]
legacy_folder_id: Mapped[int | None] = mapped_column(BigInteger)

0 comments on commit 1053f0b

Please sign in to comment.