From 36a0bab6ff9c0a9be02cf3a530ab13023f43ed8f Mon Sep 17 00:00:00 2001 From: Philipp Horstenkamp Date: Thu, 19 Oct 2023 19:21:33 +0200 Subject: [PATCH] Add relations from finanical reports to SQL (#216) --- .../models/company.py | 1 + .../utils/data_transfer.py | 61 ++++++++++--- .../utils/sql/entities.py | 4 +- tests/utils/data_transfer_test.py | 89 +++++++++++++++++++ 4 files changed, 140 insertions(+), 15 deletions(-) diff --git a/src/aki_prj23_transparenzregister/models/company.py b/src/aki_prj23_transparenzregister/models/company.py index 49abdcd..0a4c603 100644 --- a/src/aki_prj23_transparenzregister/models/company.py +++ b/src/aki_prj23_transparenzregister/models/company.py @@ -32,6 +32,7 @@ class RelationshipRoleEnum(str, MultiValueEnum): ZWEIGNIEDERLASSUNG = "Zweigniederlassung" HAUPTNIEDERLASSUNG = "Hauptniederlassung" CARE_OF = "c/o" + AUDITOR = "Auditor" class CompanyTypeEnum(str, MultiValueEnum): diff --git a/src/aki_prj23_transparenzregister/utils/data_transfer.py b/src/aki_prj23_transparenzregister/utils/data_transfer.py index 623355d..148e404 100644 --- a/src/aki_prj23_transparenzregister/utils/data_transfer.py +++ b/src/aki_prj23_transparenzregister/utils/data_transfer.py @@ -22,6 +22,7 @@ from aki_prj23_transparenzregister.models.company import ( CapitalTypeEnum, CompanyRelationshipEnum, CurrencyEnum, + RelationshipRoleEnum, ) from aki_prj23_transparenzregister.utils.logger_config import ( add_logger_options_to_argparse, @@ -524,7 +525,6 @@ def add_annual_report(company_id: int, year: int, report: dict, db: Session) -> """Ads a annual financial report to the SQL database. The added report is linked with the company. - # TODO add a link to the accountant. Args: company_id: The SQL id of the company. @@ -538,15 +538,42 @@ def add_annual_report(company_id: int, year: int, report: dict, db: Session) -> raise KeyError(f"The company with the id {company_id} could not be found.") logger.debug(f"No financial data found for {company.name} in the year {year}.") return - db.add( - entities.AnnualFinanceStatement( - company_id=company_id, - date=date(year, 1, 1), - **report.get("financials", {}), # TODO can we have a date? - ), - ) + + if report.get("financials"): + db.add( + entities.AnnualFinanceStatement( + company_id=company_id, + date=date(year, 1, 1), + **report.get("financials", {}), + ), + ) for auditor in report.get("auditors", ""): - _ = auditor + try: + company_name: str = auditor.get("company") + if not company_name: + continue + relation_to: int = get_company_id( + company_name, + None, + None, + db=db, + ) + except CompanyNotFoundError as err: + logger.debug(str(err)) + company_relation_missing(company_name, None, None, db=db) + db.commit() + return + if company_id == relation_to: + logger.warning(f"The {company_name} is auditing itself.") + return + relation = entities.CompanyRelation( + company_id=company_id, + relation=RelationshipRoleEnum.AUDITOR, + company2_id=relation_to, + date_from=date(year, 1, 1), + date_to=date(year, 12, 31), + ) + db.add(relation) def add_annual_financial_reports(companies: list[dict], db: Session) -> None: @@ -576,10 +603,10 @@ def add_annual_financial_reports(companies: list[dict], db: Session) -> None: pbar.update(len(yearly_results)) db.rollback() raise + yearly_results = { + year: report for year, report in yearly_results.items() if report + } for year, report in yearly_results.items(): - if not report: - continue - try: year_int = int(year) except ValueError: @@ -587,7 +614,15 @@ def add_annual_financial_reports(companies: list[dict], db: Session) -> None: f"The company {company['name']} has a yearly result with an invalid year of \"{year}\".", ) continue - add_annual_report(company_id, year_int, report, db=db) + try: + add_annual_report(company_id, year_int, report, db=db) + except DataInvalidError: + logger.exception( + f"While adding a financial report to {company['name']} an error has occurred." + ) + db.rollback() + else: + db.commit() pbar.update() db.commit() logger.info("Company connections added.") diff --git a/src/aki_prj23_transparenzregister/utils/sql/entities.py b/src/aki_prj23_transparenzregister/utils/sql/entities.py index a8eb2dc..b585f8c 100644 --- a/src/aki_prj23_transparenzregister/utils/sql/entities.py +++ b/src/aki_prj23_transparenzregister/utils/sql/entities.py @@ -155,8 +155,8 @@ class Relation(Base): id = sa.Column(sa.Integer, primary_key=True) company_id = sa.Column(sa.Integer, sa.ForeignKey("company.id")) - date_from = sa.Column(sa.DateTime(timezone=True), nullable=True) - date_to = sa.Column(sa.DateTime(timezone=True), nullable=True) + date_from = sa.Column(sa.Date(), nullable=True) + date_to = sa.Column(sa.Date(), nullable=True) relation = sa.Column(sa.Enum(RelationshipRoleEnum), nullable=False) diff --git a/tests/utils/data_transfer_test.py b/tests/utils/data_transfer_test.py index 28371c4..9f60741 100644 --- a/tests/utils/data_transfer_test.py +++ b/tests/utils/data_transfer_test.py @@ -19,6 +19,7 @@ from aki_prj23_transparenzregister.models.company import ( CompanyRelationshipEnum, CompanyTypeEnum, CurrencyEnum, + RelationshipRoleEnum, ) from aki_prj23_transparenzregister.utils import data_transfer from aki_prj23_transparenzregister.utils.data_transfer import CompanyNotFoundError @@ -1054,6 +1055,94 @@ def test_add_annual_report( ) +@pytest.mark.parametrize("company_id", [2, 3]) +@pytest.mark.parametrize("year", [2023, 2025, 2020]) +def test_add_annual_report_auditors( + company_id: int, + year: int, + finance_statements: list[dict[str, Any]], + full_db: Session, +) -> None: + """Tests the addition of annual financial records.""" + data_transfer.add_annual_report( + company_id, + year, + { + "auditors": [{"name": "Max Musterauditor", "company": "Some Company GmbH"}], + "financials": {}, + }, + db=full_db, + ) + full_db.commit() + added = full_db.query(entities.CompanyRelation).get(1) + assert added + assert added.company2_id == 1 + assert added.company_id == company_id + assert added.date_from == date( + year, + 1, + 1, + ) + assert added.date_to == date( + year, + 12, + 31, + ) + assert added.relation == RelationshipRoleEnum.AUDITOR + + +@pytest.mark.parametrize("company_id", [1]) +@pytest.mark.parametrize("year", [2023, 2025, 2020]) +def test_add_annual_report_self_audit( + company_id: int, + year: int, + finance_statements: list[dict[str, Any]], + full_db: Session, +) -> None: + """Tests the addition of annual financial records.""" + data_transfer.add_annual_report( + company_id, + year, + { + "auditors": [{"name": "Max Musterauditor", "company": "Some Company GmbH"}], + "financials": {}, + }, + db=full_db, + ) + full_db.commit() + assert full_db.query(entities.CompanyRelation).get(1) is None + + +@pytest.mark.parametrize("company_id", [1, 2, 3]) +@pytest.mark.parametrize("number_of_years", [1, 4, 7]) +def test_add_annual_report_unknown_audit( + company_id: int, + finance_statements: list[dict[str, Any]], + number_of_years: int, + full_db: Session, +) -> None: + """Tests the addition of annual financial records.""" + for year in range(2020, number_of_years + 2020, 1): + data_transfer.add_annual_report( + company_id, + year, + { + "auditors": [ + {"name": "Max Musterauditor", "company": "Unknown Auditor GmbH"} + ], + "financials": {}, + }, + db=full_db, + ) + full_db.commit() + added = full_db.query(entities.MissingCompany).get("Unknown Auditor GmbH") + assert added, added.__dict__ + assert added.name == "Unknown Auditor GmbH" + assert not added.zip_code + assert not added.city + assert added.number_of_links == number_of_years + + def test_add_annual_report_financial_key_error(full_db: Session) -> None: """Tests if an error is thrown financial data is tried to be added with an unknown financial record type.""" with pytest.raises(