diff --git a/src/entities/models/dao.py b/src/entities/models/dao.py index 1f0172c..1a9d643 100644 --- a/src/entities/models/dao.py +++ b/src/entities/models/dao.py @@ -21,26 +21,26 @@ class FinancialInstitutionDao(AuditMixin, Base): domains: Mapped[List["FinancialInstitutionDomainDao"]] = relationship( "FinancialInstitutionDomainDao", back_populates="fi" ) - tax_id: Mapped[str] = mapped_column(String(9), unique=True) - rssd_id: Mapped[int] = mapped_column(unique=True) - primary_federal_regulator_id: Mapped[str] = mapped_column(ForeignKey("federal_regulator.id")) + tax_id: Mapped[str] = mapped_column(String(9), unique=True, nullable=True) + rssd_id: Mapped[int] = mapped_column(unique=True, nullable=True) + primary_federal_regulator_id: Mapped[str] = mapped_column(ForeignKey("federal_regulator.id"), nullable=True) primary_federal_regulator: Mapped["FederalRegulatorDao"] = relationship(lazy="selectin") - hmda_institution_type_id: Mapped[str] = mapped_column(ForeignKey("hmda_institution_type.id")) + hmda_institution_type_id: Mapped[str] = mapped_column(ForeignKey("hmda_institution_type.id"), nullable=True) hmda_institution_type: Mapped["HMDAInstitutionTypeDao"] = relationship(lazy="selectin") - sbl_institution_type_id: Mapped[str] = mapped_column(ForeignKey("sbl_institution_type.id")) + sbl_institution_type_id: Mapped[str] = mapped_column(ForeignKey("sbl_institution_type.id"), nullable=True) sbl_institution_type: Mapped["SBLInstitutionTypeDao"] = relationship(lazy="selectin") - hq_address_street_1: Mapped[str] = mapped_column(nullable=False) - hq_address_street_2: Mapped[str] + hq_address_street_1: Mapped[str] + hq_address_street_2: Mapped[str] = mapped_column(nullable=True) hq_address_city: Mapped[str] hq_address_state_code: Mapped[str] = mapped_column(ForeignKey("address_state.code")) hq_address_state: Mapped["AddressStateDao"] = relationship(lazy="selectin") - hq_address_zip: Mapped[str] = mapped_column(String(5), nullable=False) - parent_lei: Mapped[str] = mapped_column(String(20)) - parent_legal_name: Mapped[str] - parent_rssd_id: Mapped[int] - top_holder_lei: Mapped[str] = mapped_column(String(20)) - top_holder_legal_name: Mapped[str] - top_holder_rssd_id: Mapped[int] + hq_address_zip: Mapped[str] = mapped_column(String(5)) + parent_lei: Mapped[str] = mapped_column(String(20), nullable=True) + parent_legal_name: Mapped[str] = mapped_column(nullable=True) + parent_rssd_id: Mapped[int] = mapped_column(nullable=True) + top_holder_lei: Mapped[str] = mapped_column(String(20), nullable=True) + top_holder_legal_name: Mapped[str] = mapped_column(nullable=True) + top_holder_rssd_id: Mapped[int] = mapped_column(nullable=True) class FinancialInstitutionDomainDao(AuditMixin, Base): diff --git a/src/entities/models/dto.py b/src/entities/models/dto.py index 9cea2a2..ee05131 100644 --- a/src/entities/models/dto.py +++ b/src/entities/models/dto.py @@ -19,27 +19,27 @@ class Config: class FinancialInstitutionBase(BaseModel): + lei: str name: str class FinancialInstitutionDto(FinancialInstitutionBase): - lei: str - tax_id: str - rssd_id: int - primary_federal_regulator_id: str - hmda_institution_type_id: str - sbl_institution_type_id: str + tax_id: str | None = None + rssd_id: int | None = None + primary_federal_regulator_id: str | None = None + hmda_institution_type_id: str | None = None + sbl_institution_type_id: str | None = None hq_address_street_1: str - hq_address_street_2: str + hq_address_street_2: str | None = None hq_address_city: str hq_address_state_code: str hq_address_zip: str - parent_lei: str - parent_legal_name: str - parent_rssd_id: int - top_holder_lei: str - top_holder_legal_name: str - top_holder_rssd_id: int + parent_lei: str | None = None + parent_legal_name: str | None = None + parent_rssd_id: int | None = None + top_holder_lei: str | None = None + top_holder_legal_name: str | None = None + top_holder_rssd_id: int | None = None class Config: from_attributes = True diff --git a/src/entities/repos/institutions_repo.py b/src/entities/repos/institutions_repo.py index 4597c72..4980981 100644 --- a/src/entities/repos/institutions_repo.py +++ b/src/entities/repos/institutions_repo.py @@ -74,6 +74,22 @@ async def upsert_institution(session: AsyncSession, fi: FinancialInstitutionDto) 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 await session.commit() return db_fi diff --git a/tests/api/routers/test_institutions_api.py b/tests/api/routers/test_institutions_api.py index cd6bc13..a65545a 100644 --- a/tests/api/routers/test_institutions_api.py +++ b/tests/api/routers/test_institutions_api.py @@ -79,6 +79,52 @@ def test_create_institution_authed(self, mocker: MockerFixture, app_fixture: Fas assert res.status_code == 200 assert res.json()[1].get("name") == "testName" + def test_create_institution_only_required_fields( + self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock + ): + upsert_institution_mock = mocker.patch("entities.repos.institutions_repo.upsert_institution") + upsert_institution_mock.return_value = FinancialInstitutionDao( + name="testName", + lei="testLei", + hq_address_street_1="Test Address Street 1", + hq_address_city="Test City 1", + hq_address_state_code="VA", + hq_address_zip="00000", + ) + upsert_group_mock = mocker.patch("oauth2.oauth2_admin.OAuth2Admin.upsert_group") + upsert_group_mock.return_value = "leiGroup" + client = TestClient(app_fixture) + res = client.post( + "/v1/institutions/", + json={ + "name": "testName", + "lei": "testLei", + "hq_address_street_1": "Test Address Street 1", + "hq_address_city": "Test City 1", + "hq_address_state_code": "VA", + "hq_address_zip": "00000", + }, + ) + assert res.status_code == 200 + assert res.json()[1].get("name") == "testName" + assert res.json()[1].get("tax_id") is None + + def test_create_institution_missing_required_field( + self, mocker: MockerFixture, app_fixture: FastAPI, authed_user_mock: Mock + ): + client = TestClient(app_fixture) + res = client.post( + "/v1/institutions/", + json={ + "name": "testName", + "lei": "testLei", + "hq_address_street_1": "Test Address Street 1", + "hq_address_city": "Test City 1", + "hq_address_state_code": "VA", + }, + ) + assert res.status_code == 422 + def test_create_institution_authed_no_permission(self, app_fixture: FastAPI, auth_mock: Mock): claims = { "name": "test", diff --git a/tests/entities/repos/test_institutions_repo.py b/tests/entities/repos/test_institutions_repo.py index 63d93aa..48df6e7 100644 --- a/tests/entities/repos/test_institutions_repo.py +++ b/tests/entities/repos/test_institutions_repo.py @@ -187,10 +187,50 @@ async def test_add_institution(self, transaction_session: AsyncSession): res = await repo.get_institutions(transaction_session) assert len(res) == 4 + async def test_add_institution_only_required_fields( + self, transaction_session: AsyncSession, query_session: AsyncSession + ): + await repo.upsert_institution( + transaction_session, + FinancialInstitutionDao( + name="Minimal Bank 123", + lei="MINBANK123", + hq_address_street_1="Minimal Address Street 1", + hq_address_city="Minimal City 1", + hq_address_state_code="FL", + hq_address_zip="22222", + ), + ) + res = await repo.get_institution(query_session, "MINBANK123") + assert res is not None + assert res.tax_id is None + + async def test_add_institution_missing_required_fields( + self, transaction_session: AsyncSession, query_session: AsyncSession + ): + with pytest.raises(Exception) as e: + await repo.upsert_institution( + transaction_session, + FinancialInstitutionDao( + name="Minimal Bank 123", + lei="MINBANK123", + ), + ) + assert "not null constraint failed" in str(e.value).lower() + res = await repo.get_institution(query_session, "MINBANK123") + assert res is None + async def test_update_institution(self, transaction_session: AsyncSession): await repo.upsert_institution( transaction_session, - FinancialInstitutionDao(name="Test Bank 234", lei="TESTBANK123"), + FinancialInstitutionDao( + name="Test Bank 234", + lei="TESTBANK123", + hq_address_street_1="Test Address Street 1", + hq_address_city="Test City 1", + hq_address_state_code="GA", + hq_address_zip="00000", + ), ) res = await repo.get_institutions(transaction_session) assert len(res) == 3