diff --git a/db_revisions/versions/045aa502e050_update_financial_institutions_table.py b/db_revisions/versions/045aa502e050_update_financial_institutions_table.py index 7932387..4a4122f 100644 --- a/db_revisions/versions/045aa502e050_update_financial_institutions_table.py +++ b/db_revisions/versions/045aa502e050_update_financial_institutions_table.py @@ -84,7 +84,9 @@ def downgrade() -> None: op.drop_constraint( constraint_name="fk_federal_regulator_financial_institutions", table_name="financial_institutions" ) - op.drop_constraint(constraint_name="fk_address_state_financial_institutions", table_name="financial_institutions") + op.drop_constraint( + constraint_name="fk_address_state_code_financial_institutions", table_name="financial_institutions" + ) op.drop_constraint( constraint_name="fk_hmda_institution_type_financial_institutions", table_name="financial_institutions" ) diff --git a/db_revisions/versions/383ab402c8c2_231227_add_active_field_to_institutions.py b/db_revisions/versions/383ab402c8c2_231227_add_active_field_to_institutions.py new file mode 100644 index 0000000..ee3d69e --- /dev/null +++ b/db_revisions/versions/383ab402c8c2_231227_add_active_field_to_institutions.py @@ -0,0 +1,31 @@ +"""231227 add active field to institutions table + +Revision ID: 383ab402c8c2 +Revises: a41281b1e109 +Create Date: 2023-12-27 14:21:33.567414 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = "383ab402c8c2" +down_revision: Union[str, None] = "a41281b1e109" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + with op.batch_alter_table("financial_institutions") as batch_op: + batch_op.add_column(sa.Column(name="is_active", type_=sa.Boolean(), nullable=False, server_default=sa.true())) + batch_op.create_index( + index_name=batch_op.f("ix_financial_institutions_is_active"), columns=["is_active"], unique=False + ) + + +def downgrade() -> None: + op.drop_index(index_name="ix_financial_institutions_is_active", table_name="financial_institutions") + op.drop_column(table_name="financial_institutions", column_name="is_active") diff --git a/src/entities/models/dao.py b/src/entities/models/dao.py index 1a9d643..6e11577 100644 --- a/src/entities/models/dao.py +++ b/src/entities/models/dao.py @@ -18,6 +18,7 @@ class FinancialInstitutionDao(AuditMixin, Base): __tablename__ = "financial_institutions" lei: Mapped[str] = mapped_column(unique=True, index=True, primary_key=True) name: Mapped[str] = mapped_column(index=True) + is_active: Mapped[bool] = mapped_column(index=True) domains: Mapped[List["FinancialInstitutionDomainDao"]] = relationship( "FinancialInstitutionDomainDao", back_populates="fi" ) diff --git a/src/entities/models/dto.py b/src/entities/models/dto.py index ee05131..d8a51ab 100644 --- a/src/entities/models/dto.py +++ b/src/entities/models/dto.py @@ -21,6 +21,7 @@ class Config: class FinancialInstitutionBase(BaseModel): lei: str name: str + is_active: bool class FinancialInstitutionDto(FinancialInstitutionBase): diff --git a/src/entities/repos/institutions_repo.py b/src/entities/repos/institutions_repo.py index 4980981..2af5b7b 100644 --- a/src/entities/repos/institutions_repo.py +++ b/src/entities/repos/institutions_repo.py @@ -50,46 +50,14 @@ async def upsert_institution(session: AsyncSession, fi: FinancialInstitutionDto) stmt = select(FinancialInstitutionDao).filter(FinancialInstitutionDao.lei == fi.lei) res = await session.execute(stmt) db_fi = res.scalar_one_or_none() + fi_data = fi.__dict__.copy() + fi_data.pop("_sa_instance_state", None) if db_fi is None: - db_fi = FinancialInstitutionDao( - lei=fi.lei, - name=fi.name, - tax_id=fi.tax_id, - rssd_id=fi.rssd_id, - primary_federal_regulator_id=fi.primary_federal_regulator_id, - hmda_institution_type_id=fi.hmda_institution_type_id, - sbl_institution_type_id=fi.sbl_institution_type_id, - hq_address_street_1=fi.hq_address_street_1, - hq_address_street_2=fi.hq_address_street_2, - hq_address_city=fi.hq_address_city, - hq_address_state_code=fi.hq_address_state_code, - hq_address_zip=fi.hq_address_zip, - parent_lei=fi.parent_lei, - parent_legal_name=fi.parent_legal_name, - parent_rssd_id=fi.parent_rssd_id, - top_holder_lei=fi.top_holder_lei, - top_holder_legal_name=fi.top_holder_legal_name, - top_holder_rssd_id=fi.top_holder_rssd_id, - ) + db_fi = FinancialInstitutionDao(**fi_data) session.add(db_fi) else: - db_fi.name = fi.name - db_fi.tax_id = fi.tax_id - db_fi.rssd_id = fi.rssd_id - db_fi.primary_federal_regulator_id = fi.primary_federal_regulator_id - db_fi.hmda_institution_type_id = fi.hmda_institution_type_id - db_fi.sbl_institution_type_id = fi.sbl_institution_type_id - db_fi.hq_address_street_1 = fi.hq_address_street_1 - db_fi.hq_address_street_2 = fi.hq_address_street_2 - db_fi.hq_address_city = fi.hq_address_city - db_fi.hq_address_state_code = fi.hq_address_state_code - db_fi.hq_address_zip = fi.hq_address_zip - db_fi.parent_lei = fi.parent_lei - db_fi.parent_legal_name = fi.parent_legal_name - db_fi.parent_rssd_id = fi.parent_rssd_id - db_fi.top_holder_lei = fi.top_holder_lei - db_fi.top_holder_legal_name = fi.top_holder_legal_name - db_fi.top_holder_rssd_id = fi.top_holder_rssd_id + for key, value in fi_data.items(): + setattr(db_fi, key, value) await session.commit() return db_fi diff --git a/src/routers/institutions.py b/src/routers/institutions.py index 371c2ee..2018216 100644 --- a/src/routers/institutions.py +++ b/src/routers/institutions.py @@ -56,24 +56,7 @@ async def get_associated_institutions(request: Request): associated_institutions = await repo.get_institutions(request.state.db_session, user.institutions) return [ FinanicialInstitutionAssociationDto( - name=institution.name, - lei=institution.lei, - tax_id=institution.tax_id, - rssd_id=institution.rssd_id, - primary_federal_regulator_id=institution.primary_federal_regulator_id, - hmda_institution_type_id=institution.hmda_institution_type_id, - sbl_institution_type_id=institution.sbl_institution_type_id, - hq_address_street_1=institution.hq_address_street_1, - hq_address_street_2=institution.hq_address_street_2, - hq_address_city=institution.hq_address_city, - hq_address_state_code=institution.hq_address_state_code, - hq_address_zip=institution.hq_address_zip, - parent_lei=institution.parent_lei, - parent_legal_name=institution.parent_legal_name, - parent_rssd_id=institution.parent_rssd_id, - top_holder_lei=institution.top_holder_lei, - top_holder_legal_name=institution.top_holder_legal_name, - top_holder_rssd_id=institution.top_holder_rssd_id, + **institution.__dict__, approved=email_domain in [inst_domain.domain for inst_domain in institution.domains], ) for institution in associated_institutions diff --git a/tests/api/conftest.py b/tests/api/conftest.py index 73577f4..b466130 100644 --- a/tests/api/conftest.py +++ b/tests/api/conftest.py @@ -54,6 +54,7 @@ def get_institutions_mock(mocker: MockerFixture) -> Mock: FinancialInstitutionDao( name="Test Bank 123", lei="TESTBANK123", + is_active=True, domains=[FinancialInstitutionDomainDao(domain="test.bank", lei="TESTBANK123")], tax_id="123456789", rssd_id=1234, diff --git a/tests/api/routers/test_institutions_api.py b/tests/api/routers/test_institutions_api.py index a65545a..12553d0 100644 --- a/tests/api/routers/test_institutions_api.py +++ b/tests/api/routers/test_institutions_api.py @@ -32,6 +32,7 @@ def test_create_institution_authed(self, mocker: MockerFixture, app_fixture: Fas upsert_institution_mock.return_value = FinancialInstitutionDao( name="testName", lei="testLei", + is_active=True, domains=[FinancialInstitutionDomainDao(domain="test.bank", lei="TESTBANK123")], tax_id="123456789", rssd_id=1234, @@ -58,6 +59,7 @@ def test_create_institution_authed(self, mocker: MockerFixture, app_fixture: Fas json={ "name": "testName", "lei": "testLei", + "is_active": True, "tax_id": "123456789", "rssd_id": 12344, "primary_federal_regulator_id": "FRI2", @@ -86,6 +88,7 @@ def test_create_institution_only_required_fields( upsert_institution_mock.return_value = FinancialInstitutionDao( name="testName", lei="testLei", + is_active=True, hq_address_street_1="Test Address Street 1", hq_address_city="Test City 1", hq_address_state_code="VA", @@ -99,6 +102,7 @@ def test_create_institution_only_required_fields( json={ "name": "testName", "lei": "testLei", + "is_active": True, "hq_address_street_1": "Test Address Street 1", "hq_address_city": "Test City 1", "hq_address_state_code": "VA", @@ -142,6 +146,7 @@ def test_create_institution_authed_no_permission(self, app_fixture: FastAPI, aut json={ "name": "testName", "lei": "testLei", + "is_active": True, "tax_id": "123456789", "rssd_id": 12344, "primary_federal_regulator_id": "FIR2", @@ -173,6 +178,7 @@ def test_get_institution_authed(self, mocker: MockerFixture, app_fixture: FastAP get_institution_mock.return_value = FinancialInstitutionDao( name="Test Bank 123", lei="TESTBANK123", + is_active=True, domains=[FinancialInstitutionDomainDao(domain="test.bank", lei="TESTBANK123")], tax_id="123456789", rssd_id=1234, @@ -266,6 +272,7 @@ def test_get_associated_institutions( FinancialInstitutionDao( name="Test Bank 123", lei="TESTBANK123", + is_active=True, domains=[FinancialInstitutionDomainDao(domain="test123.bank", lei="TESTBANK123")], tax_id="123456789", rssd_id=1234, @@ -287,6 +294,7 @@ def test_get_associated_institutions( FinancialInstitutionDao( name="Test Bank 234", lei="TESTBANK234", + is_active=True, domains=[FinancialInstitutionDomainDao(domain="test234.bank", lei="TESTBANK234")], tax_id="123456879", rssd_id=6879, diff --git a/tests/entities/repos/test_institutions_repo.py b/tests/entities/repos/test_institutions_repo.py index 48df6e7..50eee18 100644 --- a/tests/entities/repos/test_institutions_repo.py +++ b/tests/entities/repos/test_institutions_repo.py @@ -46,6 +46,7 @@ async def setup( FinancialInstitutionDao( name="Test Bank 123", lei="TESTBANK123", + is_active=True, domains=[FinancialInstitutionDomainDao(domain="test.bank.1", lei="TESTBANK123")], tax_id="123456789", rssd_id=1234, @@ -67,6 +68,7 @@ async def setup( FinancialInstitutionDao( name="Test Bank 456", lei="TESTBANK456", + is_active=True, domains=[FinancialInstitutionDomainDao(domain="test.bank.2", lei="TESTBANK456")], tax_id="987654321", rssd_id=4321, @@ -88,6 +90,7 @@ async def setup( FinancialInstitutionDao( name="Test Sub Bank 456", lei="TESTSUBBANK456", + is_active=True, domains=[FinancialInstitutionDomainDao(domain="sub.test.bank.2", lei="TESTSUBBANK456")], tax_id="765432198", rssd_id=2134, @@ -166,6 +169,7 @@ async def test_add_institution(self, transaction_session: AsyncSession): FinancialInstitutionDao( name="New Bank 123", lei="NEWBANK123", + is_active=True, tax_id="654321987", rssd_id=6543, primary_federal_regulator_id="FRI3", @@ -195,6 +199,7 @@ async def test_add_institution_only_required_fields( FinancialInstitutionDao( name="Minimal Bank 123", lei="MINBANK123", + is_active=True, hq_address_street_1="Minimal Address Street 1", hq_address_city="Minimal City 1", hq_address_state_code="FL", @@ -226,6 +231,7 @@ async def test_update_institution(self, transaction_session: AsyncSession): FinancialInstitutionDao( name="Test Bank 234", lei="TESTBANK123", + is_active=True, hq_address_street_1="Test Address Street 1", hq_address_city="Test City 1", hq_address_state_code="GA",