Skip to content

Commit

Permalink
Merge branch 'main' into 69-add-endpoints-to-retrieve-from-look-up-da…
Browse files Browse the repository at this point in the history
…ta-tables
  • Loading branch information
jcadam14 committed Dec 28, 2023
2 parents 441880c + 219a8ae commit 4ccae37
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -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")
4 changes: 2 additions & 2 deletions src/entities/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"FinancialInstitutionDao",
"FinancialInstitutionDomainDao",
"FinancialInstitutionDto",
"FinancialInstitutionWithDomainsDto",
"FinancialInstitutionWithRelationsDto",
"FinancialInsitutionDomainDto",
"FinancialInsitutionDomainCreate",
"FinanicialInstitutionAssociationDto",
Expand Down Expand Up @@ -34,7 +34,7 @@
)
from .dto import (
FinancialInstitutionDto,
FinancialInstitutionWithDomainsDto,
FinancialInstitutionWithRelationsDto,
FinancialInsitutionDomainDto,
FinancialInsitutionDomainCreate,
FinanicialInstitutionAssociationDto,
Expand Down
1 change: 1 addition & 0 deletions src/entities/models/dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down
49 changes: 18 additions & 31 deletions src/entities/models/dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Config:
class FinancialInstitutionBase(BaseModel):
lei: str
name: str
is_active: bool


class FinancialInstitutionDto(FinancialInstitutionBase):
Expand All @@ -45,10 +46,6 @@ class Config:
from_attributes = True


class FinancialInstitutionWithDomainsDto(FinancialInstitutionDto):
domains: List[FinancialInsitutionDomainDto] = []


class DeniedDomainDto(BaseModel):
domain: str

Expand All @@ -65,10 +62,6 @@ def to_keycloak_user(self):
return {"firstName": self.first_name, "lastName": self.last_name}


class FinanicialInstitutionAssociationDto(FinancialInstitutionDto):
approved: bool


class FederalRegulatorBase(BaseModel):
id: str

Expand All @@ -88,30 +81,12 @@ class Config:
from_attributes = True


# Let this in here just in case the 'generic' InstitutionTypeDto approach isn't desired
#
# class HMDAInstitutionTypeBase(BaseModel):
# id: str


# class HMDAInstitutionTypeDto(HMDAInstitutionTypeBase):
# name: str
#
# class Config:
# from_attributes = True


# class SBLInstitutionTypeBase(BaseModel):
# id: str


# class SBLInstitutionTypeDto(SBLInstitutionTypeBase):
# name: str
#
# class Config:
# from_attributes = True

class HMDAInstitutionTypeDto(InstitutionTypeDto):
pass

class SBLInstitutionTypeDto(InstitutionTypeDto):
pass

class AddressStateBase(BaseModel):
code: str

Expand All @@ -123,6 +98,18 @@ class Config:
from_attributes = True


class FinancialInstitutionWithRelationsDto(FinancialInstitutionDto):
primary_federal_regulator: FederalRegulatorDto | None = None
hmda_institution_type: HMDAInstitutionTypeDto | None = None
sbl_institution_type: SBLInstitutionTypeDto | None = None
hq_address_state: AddressStateDto
domains: List[FinancialInsitutionDomainDto] = []


class FinanicialInstitutionAssociationDto(FinancialInstitutionWithRelationsDto):
approved: bool


class AuthenticatedUser(BaseUser, BaseModel):
claims: Dict[str, Any]
name: str
Expand Down
42 changes: 5 additions & 37 deletions src/entities/repos/institutions_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,46 +82,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

Expand Down
27 changes: 5 additions & 22 deletions src/routers/institutions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from entities.repos import institutions_repo as repo
from entities.models import (
FinancialInstitutionDto,
FinancialInstitutionWithDomainsDto,
FinancialInstitutionWithRelationsDto,
FinancialInsitutionDomainDto,
FinancialInsitutionDomainCreate,
FinanicialInstitutionAssociationDto,
Expand All @@ -32,7 +32,7 @@ async def set_db(request: Request, session: Annotated[AsyncSession, Depends(get_
router = Router(dependencies=[Depends(set_db)])


@router.get("/", response_model=List[FinancialInstitutionWithDomainsDto])
@router.get("/", response_model=List[FinancialInstitutionWithRelationsDto])
@requires("authenticated")
async def get_institutions(
request: Request,
Expand All @@ -44,7 +44,7 @@ async def get_institutions(
return await repo.get_institutions(request.state.db_session, leis, domain, page, count)


@router.post("/", response_model=Tuple[str, FinancialInstitutionDto], dependencies=[Depends(check_domain)])
@router.post("/", response_model=Tuple[str, FinancialInstitutionWithRelationsDto], dependencies=[Depends(check_domain)])
@requires(["query-groups", "manage-users"])
async def create_institution(
request: Request,
Expand All @@ -63,24 +63,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
Expand Down Expand Up @@ -108,7 +91,7 @@ async def get_federal_regulators(request: Request):
return await repo.get_federal_regulators(request.state.db_session)


@router.get("/{lei}", response_model=FinancialInstitutionWithDomainsDto)
@router.get("/{lei}", response_model=FinancialInstitutionWithRelationsDto)
@requires("authenticated")
async def get_institution(
request: Request,
Expand Down
15 changes: 14 additions & 1 deletion tests/api/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@
from pytest_mock import MockerFixture
from starlette.authentication import AuthCredentials, UnauthenticatedUser

from entities.models import AuthenticatedUser, FinancialInstitutionDao, FinancialInstitutionDomainDao
from entities.models import (
AuthenticatedUser,
FinancialInstitutionDao,
FinancialInstitutionDomainDao,
FederalRegulatorDao,
AddressStateDao,
HMDAInstitutionTypeDao,
SBLInstitutionTypeDao,
)


@pytest.fixture
Expand Down Expand Up @@ -54,16 +62,21 @@ 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,
primary_federal_regulator_id="FRI1",
primary_federal_regulator=FederalRegulatorDao(id="FRI1", name="FRI1"),
hmda_institution_type_id="HIT1",
hmda_institution_type=HMDAInstitutionTypeDao(id="HIT1", name="HIT1"),
sbl_institution_type_id="SIT1",
sbl_institution_type=SBLInstitutionTypeDao(id="SIT1", name="SIT1"),
hq_address_street_1="Test Address Street 1",
hq_address_street_2="",
hq_address_city="Test City 1",
hq_address_state_code="GA",
hq_address_state=AddressStateDao(code="GA", name="Georgia"),
hq_address_zip="00000",
parent_lei="PARENTTESTBANK123",
parent_legal_name="PARENT TEST BANK 123",
Expand Down
Loading

0 comments on commit 4ccae37

Please sign in to comment.