From b9f6ab94f1f76161923723f3d4616d4e332c676b Mon Sep 17 00:00:00 2001 From: John DeAngelis Date: Thu, 14 Nov 2024 09:22:58 -0500 Subject: [PATCH] fix: add logic for empty fund code and appropriation year Signed-off-by: John DeAngelis --- backend/data_tools/src/load_cans/utils.py | 9 +++- .../tests/load_cans/test_load_cans.py | 45 ++++++++++++++++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/backend/data_tools/src/load_cans/utils.py b/backend/data_tools/src/load_cans/utils.py index c2a4d13b90..d7cca7b22b 100644 --- a/backend/data_tools/src/load_cans/utils.py +++ b/backend/data_tools/src/load_cans/utils.py @@ -122,10 +122,10 @@ def create_models(data: CANData, sys_user: User, session: Session) -> None: try: validate_fund_code(data) + can.funding_details = get_or_create_funding_details(data, sys_user, session) except ValueError as e: logger.info(f"Skipping creating funding details for {data} due to invalid fund code. {e}") - can.funding_details = get_or_create_funding_details(data, sys_user, session) session.merge(can) session.commit() except Exception as e: @@ -148,7 +148,10 @@ def get_or_create_funding_details(data: CANData, sys_user: User, session: Sessio allowance = data.ALLOWANCE sub_allowance = data.SUB_ALLOWANCE allotment = data.ALLOTMENT_ORG - appropriation = "-".join([data.APPROP_PREFIX or "", data.APPROP_YEAR[0:2] or "", data.APPROP_POSTFIX or ""]) + + appropriation_year = data.APPROP_YEAR[0:2] if data.APPROP_YEAR else "" + appropriation = "-".join([data.APPROP_PREFIX or "", appropriation_year, data.APPROP_POSTFIX or ""]) + method_of_transfer = CANMethodOfTransfer[data.METHOD_OF_TRANSFER] funding_source = CANFundingSource[data.FUNDING_SOURCE] existing_funding_details = session.execute(select(CANFundingDetails).where( @@ -188,6 +191,8 @@ def validate_fund_code(data: CANData) -> None: :return: None :raises ValueError: If the fund code is invalid. """ + if not data.FUND: + raise ValueError("Fund code is required.") if len(data.FUND) != 14: raise ValueError(f"Invalid fund code length {data.FUND}") int(data.FUND[6:10]) diff --git a/backend/data_tools/tests/load_cans/test_load_cans.py b/backend/data_tools/tests/load_cans/test_load_cans.py index 3b2b52ce7f..b4bba28d94 100644 --- a/backend/data_tools/tests/load_cans/test_load_cans.py +++ b/backend/data_tools/tests/load_cans/test_load_cans.py @@ -302,7 +302,7 @@ def test_create_models_upsert(db_with_portfolios): SYS_CAN_ID=500, CAN_NBR="G99HRF3", CAN_DESCRIPTION="Healthy Marriages Responsible Fatherhood - OPRE", - FUND="AAXXXX20231DAE", + FUND="AAXXXX20231DAM", ALLOWANCE="0000000001", ALLOTMENT_ORG="YZC6S1JUGUN", SUB_ALLOWANCE="9KRZ2ND", @@ -364,7 +364,7 @@ def test_create_models_upsert(db_with_portfolios): assert can_1.portfolio == db_with_portfolios.execute( select(Portfolio).where(Portfolio.abbreviation == "HMRF")).scalar_one_or_none() assert can_1.funding_details.id == db_with_portfolios.execute( - select(CANFundingDetails).where(CANFundingDetails.fund_code == "AAXXXX20231DAE")).scalar_one_or_none().id + select(CANFundingDetails).where(CANFundingDetails.fund_code == "AAXXXX20231DAM")).scalar_one_or_none().id assert can_1.created_by == sys_user.id assert len(db_with_portfolios.execute(select(CAN)).scalars().all()) == 1 @@ -530,3 +530,44 @@ def test_validate_fund_code_discretionary_or_mandatory(): with pytest.raises(ValueError) as e_info: validate_fund_code(data) assert e_info.value.args[0] == "Invalid discretionary or mandatory R" + +def test_create_models_invalid_fund_code(db_with_portfolios): + data = CANData( + SYS_CAN_ID=500, + CAN_NBR="G99HRF2", + CAN_DESCRIPTION="Healthy Marriages Responsible Fatherhood - OPRE", + FUND="AAXXXX20231DADDDDDD", + ALLOWANCE="0000000001", + ALLOTMENT_ORG="YZC6S1JUGUN", + SUB_ALLOWANCE="9KRZ2ND", + CURRENT_FY_FUNDING_YTD=880000.0, + APPROP_PREFIX="XX", + APPROP_POSTFIX="XXXX", + APPROP_YEAR="23", + PORTFOLIO="HMRF", + FUNDING_SOURCE="OPRE", + METHOD_OF_TRANSFER="DIRECT", + NICK_NAME="HMRF-OPRE", + ) + + sys_user = User( + email="system.admin@localhost", + ) + create_models(data, sys_user, db_with_portfolios) + + can_model = db_with_portfolios.get(CAN, 500) + + assert can_model.id == 500 + assert can_model.number == "G99HRF2" + assert can_model.description == "Healthy Marriages Responsible Fatherhood - OPRE" + assert can_model.nick_name == "HMRF-OPRE" + assert can_model.portfolio == db_with_portfolios.execute(select(Portfolio).where(Portfolio.abbreviation == "HMRF")).scalar_one_or_none() + assert can_model.funding_details is None + + # Cleanup + db_with_portfolios.execute(text("DELETE FROM can")) + db_with_portfolios.execute(text("DELETE FROM can_funding_details")) + db_with_portfolios.execute(text("DELETE FROM can_version")) + db_with_portfolios.execute(text("DELETE FROM can_funding_details_version")) + db_with_portfolios.execute(text("DELETE FROM ops_db_history")) + db_with_portfolios.execute(text("DELETE FROM ops_db_history_version"))