diff --git a/.vscode/launch.json b/.vscode/launch.json index 1ed22440..2c7064ae 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -96,7 +96,21 @@ "cwd": "${workspaceFolder}", "env": { "PYTHONPATH":"${workspaceFolder}"}, "envFile": "${workspaceFolder}/.env.development", + "justMyCode": false + }, + { + "name": "Load FAB Round", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/scripts/fund_round_loaders/load_fund_round_from_fab.py", + "console": "integratedTerminal", + "host": "localhost", + "port": 9091, + "cwd": "${workspaceFolder}", + "env": { "PYTHONPATH":"${workspaceFolder}"}, + "envFile": "${workspaceFolder}/.env.development", "justMyCode": false, + "args": ["--fund_short_code", "COF25-EOI"] }, { "name": "Amend Round dates", diff --git a/config/fund_loader_config/FAB/__init__.py b/config/fund_loader_config/FAB/__init__.py new file mode 100644 index 00000000..91b6e318 --- /dev/null +++ b/config/fund_loader_config/FAB/__init__.py @@ -0,0 +1,39 @@ +import ast +import os +from pathlib import Path + +""" +Goes through all the files in config/fund_loader_config/FAB and adds each round to FAB_FUND_ROUND_CONFIGS + +Each file in that directory needs to be python format as per the FAB exports, +containing one property called LOADER_CONFIG +See test_fab_round_config.py for example +""" + +FAB_FUND_ROUND_CONFIGS = {} + +this_dir = Path("config") / "fund_loader_config" / "FAB" + +for file in os.listdir(this_dir): + if "__" in file.title(): + continue + with open(this_dir / file, "r") as json_file: + + content = json_file.read().split("LOADER_CONFIG=")[1] + loader_config = ast.literal_eval(content) + if not loader_config.get("fund_config", None): + print("No fund config found in the loader config.") + raise ValueError(f"No fund_config found in {file}") + if not loader_config.get("round_config", None): + print("No round config found in the loader config.") + raise ValueError(f"No round_config found in {file}") + fund_short_name = loader_config["fund_config"]["short_name"] + round_short_name = loader_config["round_config"]["short_name"] + FAB_FUND_ROUND_CONFIGS[fund_short_name] = loader_config["fund_config"] + if not FAB_FUND_ROUND_CONFIGS[fund_short_name].get("rounds", None): + FAB_FUND_ROUND_CONFIGS[fund_short_name]["rounds"] = {} + FAB_FUND_ROUND_CONFIGS[fund_short_name]["rounds"][round_short_name] = loader_config["round_config"] + FAB_FUND_ROUND_CONFIGS[fund_short_name]["rounds"][round_short_name]["sections_config"] = loader_config[ + "sections_config" + ] + FAB_FUND_ROUND_CONFIGS[fund_short_name]["rounds"][round_short_name]["base_path"] = loader_config["base_path"] diff --git a/config/fund_loader_config/common_fund_config/fund_base_tree_paths.py b/config/fund_loader_config/common_fund_config/fund_base_tree_paths.py index f6428d53..dfb07179 100644 --- a/config/fund_loader_config/common_fund_config/fund_base_tree_paths.py +++ b/config/fund_loader_config/common_fund_config/fund_base_tree_paths.py @@ -1,5 +1,6 @@ # Should increment for each new round, anything that shares the same base path will also share # the child tree path config. +# COF_R2_W2_BASE_PATH = 1 COF_R2_W3_BASE_PATH = 1 COF_R3_W1_BASE_PATH = 2 @@ -12,3 +13,5 @@ COF_R4_W1_BASE_PATH = 9 HSRA_BASE_PATH = 10 COF_R4_W2_BASE_PATH = 11 + +FAB_BASE_PATH = 0 diff --git a/db/queries.py b/db/queries.py index 559b5518..2c2cc1e4 100644 --- a/db/queries.py +++ b/db/queries.py @@ -235,7 +235,7 @@ def insert_sections(sections): db.session.commit() -def insert_fund_data(fund_config): +def insert_fund_data(fund_config, commit: bool = True): stmt = ( ( postgres_insert(Fund).values( @@ -283,101 +283,116 @@ def insert_fund_data(fund_config): result = db.session.execute(stmt, update_params) inserted_fund_ids = [row.id for row in result] - db.session.commit() - print(f"Inserted funds: '{inserted_fund_ids}'.") + + print(f"Prepared fund for insert: '{inserted_fund_ids}'.") + if commit: + db.session.commit() + print("DB changes committed") return inserted_fund_ids -def insert_round_data(round_config): +def upsert_round_data(round_configs, commit: bool = True): # Create dictionary to store updated records updated_rounds = {} - for item in round_config: + for round_config in round_configs: # Check if record exist - round_record = Round.query.filter_by(id=item["id"]).first() + round_record = Round.query.filter_by(id=round_config["id"]).first() if round_record is not None: # Update existing round record - round_record.title_json = item["title_json"] - round_record.short_name = item["short_name"] - round_record.opens = item["opens"] - round_record.assessment_start = item["assessment_start"] - round_record.deadline = item["deadline"] - round_record.application_reminder_sent = item["application_reminder_sent"] - round_record.reminder_date = item["reminder_date"] - round_record.fund_id = item["fund_id"] - round_record.assessment_deadline = item["assessment_deadline"] - round_record.prospectus = item["prospectus"] - round_record.privacy_notice = item["privacy_notice"] - round_record.reference_contact_page_over_email = item["reference_contact_page_over_email"] - round_record.contact_us_banner_json = item["contact_us_banner_json"] - round_record.contact_email = item["contact_email"] - round_record.contact_phone = item["contact_phone"] - round_record.contact_textphone = item["contact_textphone"] - round_record.support_times = item["support_times"] - round_record.support_days = item["support_days"] - round_record.instructions_json = item["instructions_json"] - round_record.project_name_field_id = item["project_name_field_id"] - round_record.feedback_link = item["feedback_link"] - round_record.application_guidance_json = item["application_guidance_json"] - round_record.guidance_url = item["guidance_url"] - round_record.all_uploaded_documents_section_available = item["all_uploaded_documents_section_available"] - round_record.application_fields_download_available = item["application_fields_download_available"] - round_record.display_logo_on_pdf_exports = item["display_logo_on_pdf_exports"] - round_record.feedback_survey_config = item["feedback_survey_config"] - round_record.mark_as_complete_enabled = item["mark_as_complete_enabled"] - round_record.is_expression_of_interest = item["is_expression_of_interest"] - round_record.eligibility_config = item["eligibility_config"] - round_record.eoi_decision_schema = item["eoi_decision_schema"] - - updated_rounds[item["id"]] = round_record + round_record.title_json = round_config["title_json"] + round_record.short_name = round_config["short_name"] + round_record.opens = round_config["opens"] + round_record.assessment_start = round_config["assessment_start"] + round_record.deadline = round_config["deadline"] + round_record.application_reminder_sent = round_config["application_reminder_sent"] + round_record.reminder_date = round_config["reminder_date"] + round_record.fund_id = round_config["fund_id"] + round_record.assessment_deadline = round_config["assessment_deadline"] + round_record.prospectus = round_config["prospectus"] + round_record.privacy_notice = round_config["privacy_notice"] + round_record.reference_contact_page_over_email = round_config["reference_contact_page_over_email"] + round_record.contact_us_banner_json = round_config["contact_us_banner_json"] + round_record.contact_email = round_config["contact_email"] + round_record.contact_phone = round_config["contact_phone"] + round_record.contact_textphone = round_config["contact_textphone"] + round_record.support_times = round_config["support_times"] + round_record.support_days = round_config["support_days"] + round_record.instructions_json = round_config["instructions_json"] + round_record.project_name_field_id = round_config["project_name_field_id"] + round_record.feedback_link = round_config["feedback_link"] + round_record.application_guidance_json = round_config["application_guidance_json"] + round_record.guidance_url = round_config["guidance_url"] + round_record.all_uploaded_documents_section_available = round_config[ + "all_uploaded_documents_section_available" + ] + round_record.application_fields_download_available = round_config["application_fields_download_available"] + round_record.display_logo_on_pdf_exports = round_config["display_logo_on_pdf_exports"] + round_record.feedback_survey_config = round_config["feedback_survey_config"] + round_record.mark_as_complete_enabled = round_config["mark_as_complete_enabled"] + round_record.is_expression_of_interest = round_config["is_expression_of_interest"] + round_record.eligibility_config = round_config["eligibility_config"] + round_record.eoi_decision_schema = round_config["eoi_decision_schema"] + + updated_rounds[round_config["id"]] = round_record else: # Insert new round record new_round = Round( - id=item["id"], - title_json=item["title_json"], - short_name=item["short_name"], - opens=item["opens"], - assessment_start=item["assessment_start"], - deadline=item["deadline"], - application_reminder_sent=item["application_reminder_sent"], - reminder_date=item["reminder_date"], - fund_id=item["fund_id"], - assessment_deadline=item["assessment_deadline"], - prospectus=item["prospectus"], - privacy_notice=item["privacy_notice"], - reference_contact_page_over_email=item["reference_contact_page_over_email"], - contact_us_banner_json=item["contact_us_banner_json"], - contact_email=item["contact_email"], - contact_phone=item["contact_phone"], - contact_textphone=item["contact_textphone"], - support_times=item["support_times"], - support_days=item["support_days"], - instructions_json=item["instructions_json"], - project_name_field_id=item["project_name_field_id"], - feedback_link=item["feedback_link"], - application_guidance_json=item["application_guidance_json"], - guidance_url=item["guidance_url"], - all_uploaded_documents_section_available=item["all_uploaded_documents_section_available"], - application_fields_download_available=item["application_fields_download_available"], - display_logo_on_pdf_exports=item["display_logo_on_pdf_exports"], - feedback_survey_config=item["feedback_survey_config"], - mark_as_complete_enabled=item["mark_as_complete_enabled"], - is_expression_of_interest=item["is_expression_of_interest"], - eligibility_config=item["eligibility_config"], - eoi_decision_schema=item["eoi_decision_schema"], + id=round_config["id"], + title_json=round_config["title_json"], + short_name=round_config["short_name"], + opens=round_config["opens"], + assessment_start=round_config["assessment_start"], + deadline=round_config["deadline"], + application_reminder_sent=round_config["application_reminder_sent"], + reminder_date=round_config["reminder_date"], + fund_id=round_config["fund_id"], + assessment_deadline=round_config["assessment_deadline"], + prospectus=round_config["prospectus"], + privacy_notice=round_config["privacy_notice"], + reference_contact_page_over_email=round_config["reference_contact_page_over_email"], + contact_us_banner_json=round_config["contact_us_banner_json"], + contact_email=round_config["contact_email"], + contact_phone=round_config["contact_phone"], + contact_textphone=round_config["contact_textphone"], + support_times=round_config["support_times"], + support_days=round_config["support_days"], + instructions_json=round_config["instructions_json"], + project_name_field_id=round_config["project_name_field_id"], + feedback_link=round_config["feedback_link"], + application_guidance_json=round_config["application_guidance_json"], + guidance_url=round_config["guidance_url"], + all_uploaded_documents_section_available=round_config["all_uploaded_documents_section_available"], + application_fields_download_available=round_config["application_fields_download_available"], + display_logo_on_pdf_exports=round_config["display_logo_on_pdf_exports"], + feedback_survey_config=round_config["feedback_survey_config"], + mark_as_complete_enabled=round_config["mark_as_complete_enabled"], + is_expression_of_interest=round_config["is_expression_of_interest"], + eligibility_config=round_config["eligibility_config"], + eoi_decision_schema=round_config["eoi_decision_schema"], ) db.session.add(new_round) - updated_rounds[item["id"]] = new_round + updated_rounds[round_config["id"]] = new_round - db.session.commit() - print(f"Inserted rounds: '{updated_rounds}'.") + print(f"Prepared rounds for insert: '{updated_rounds}'.") + if commit: + db.session.commit() + print("DB changes committed") return updated_rounds def insert_base_sections(APPLICATION_BASE_PATH, ASSESSMENT_BASE_PATH, round_id): + """ + Insert base sections for a fund round. + + :param APPLICATION_BASE_PATH: The base path for the application sections. + :param ASSESSMENT_BASE_PATH: The base path for the assessment sections. + :param round_id: The id of the round to insert the sections for. + :return: A dictionary of the inserted sections. + """ tree_base_sections = [ { "section_name": {"en": "Application", "cy": "Application"}, @@ -419,13 +434,12 @@ def insert_base_sections(APPLICATION_BASE_PATH, ASSESSMENT_BASE_PATH, round_id): updated_sections[section["tree_path"]] = new_section - db.session.commit() - print(f"Inserted sections: '{updated_sections}'.") + print(f"Prepared sections for insert: '{updated_sections}'.") return updated_sections def insert_or_update_application_sections(round_id, sorted_application_sections: dict): - print(f"Inserting forms config: '{sorted_application_sections}'.") + print(f"Preparing insert for sections config: '{sorted_application_sections}'.") updated_sections = {} for section in sorted_application_sections: section_record = Section.query.filter( @@ -469,7 +483,7 @@ def insert_or_update_application_sections(round_id, sorted_application_sections: db.session.add(new_form_record) print(f"Inserted form name information: '{new_form_record}'.") db.session.commit() - print("Section UPDATES and INSERTS committed.") + print("Section UPDATES and INSERTS Prepared for insert.") return updated_sections diff --git a/scripts/data_updates/FS-2433-application_guidance.py b/scripts/data_updates/FS-2433-application_guidance.py index 3832c541..459b0846 100644 --- a/scripts/data_updates/FS-2433-application_guidance.py +++ b/scripts/data_updates/FS-2433-application_guidance.py @@ -32,5 +32,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-2900-ns-section-update.py b/scripts/data_updates/FS-2900-ns-section-update.py index 26ad8643..189cbebd 100644 --- a/scripts/data_updates/FS-2900-ns-section-update.py +++ b/scripts/data_updates/FS-2900-ns-section-update.py @@ -51,5 +51,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-2965_ns_guidance.py b/scripts/data_updates/FS-2965_ns_guidance.py index c87d2449..da633578 100644 --- a/scripts/data_updates/FS-2965_ns_guidance.py +++ b/scripts/data_updates/FS-2965_ns_guidance.py @@ -34,5 +34,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-2982-date-logic.py b/scripts/data_updates/FS-2982-date-logic.py index 798c1ff3..cd7b1a38 100644 --- a/scripts/data_updates/FS-2982-date-logic.py +++ b/scripts/data_updates/FS-2982-date-logic.py @@ -34,5 +34,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-3471-application_guidance.py b/scripts/data_updates/FS-3471-application_guidance.py index f1c81619..9bc86159 100644 --- a/scripts/data_updates/FS-3471-application_guidance.py +++ b/scripts/data_updates/FS-3471-application_guidance.py @@ -30,5 +30,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-3749_dpif_guidance_url.py b/scripts/data_updates/FS-3749_dpif_guidance_url.py index a97274ad..f79acd5b 100644 --- a/scripts/data_updates/FS-3749_dpif_guidance_url.py +++ b/scripts/data_updates/FS-3749_dpif_guidance_url.py @@ -34,5 +34,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-3808_dpif_application_fields_download_available.py b/scripts/data_updates/FS-3808_dpif_application_fields_download_available.py index 3f29210c..5e0412f5 100644 --- a/scripts/data_updates/FS-3808_dpif_application_fields_download_available.py +++ b/scripts/data_updates/FS-3808_dpif_application_fields_download_available.py @@ -34,5 +34,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-3859_patch_cof_r3w3_section_names.py b/scripts/data_updates/FS-3859_patch_cof_r3w3_section_names.py index 371046ad..c989b8b7 100644 --- a/scripts/data_updates/FS-3859_patch_cof_r3w3_section_names.py +++ b/scripts/data_updates/FS-3859_patch_cof_r3w3_section_names.py @@ -12,5 +12,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-3866_fix_incorrect_instructions_url.py b/scripts/data_updates/FS-3866_fix_incorrect_instructions_url.py index 4f133fc5..35fd3770 100644 --- a/scripts/data_updates/FS-3866_fix_incorrect_instructions_url.py +++ b/scripts/data_updates/FS-3866_fix_incorrect_instructions_url.py @@ -34,5 +34,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS-4264_update_eoi_welsh_instructions.py b/scripts/data_updates/FS-4264_update_eoi_welsh_instructions.py index 8c01ed86..cd400bfd 100644 --- a/scripts/data_updates/FS-4264_update_eoi_welsh_instructions.py +++ b/scripts/data_updates/FS-4264_update_eoi_welsh_instructions.py @@ -31,5 +31,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS2910_ns_links.py b/scripts/data_updates/FS2910_ns_links.py index 4e25804a..f36cde96 100644 --- a/scripts/data_updates/FS2910_ns_links.py +++ b/scripts/data_updates/FS2910_ns_links.py @@ -35,5 +35,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/FS2956_ns_weightings.py b/scripts/data_updates/FS2956_ns_weightings.py index 753f5e33..43552fc7 100644 --- a/scripts/data_updates/FS2956_ns_weightings.py +++ b/scripts/data_updates/FS2956_ns_weightings.py @@ -32,5 +32,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/patch_cof_r3w1_section_names.py b/scripts/data_updates/patch_cof_r3w1_section_names.py index 815ef4c3..7644a350 100644 --- a/scripts/data_updates/patch_cof_r3w1_section_names.py +++ b/scripts/data_updates/patch_cof_r3w1_section_names.py @@ -12,5 +12,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/patch_cyp_name.py b/scripts/data_updates/patch_cyp_name.py index 871cb336..e16367d6 100644 --- a/scripts/data_updates/patch_cyp_name.py +++ b/scripts/data_updates/patch_cyp_name.py @@ -24,5 +24,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/data_updates/patch_cypr1_guidance_201023.py b/scripts/data_updates/patch_cypr1_guidance_201023.py index a23cde40..c402f553 100644 --- a/scripts/data_updates/patch_cypr1_guidance_201023.py +++ b/scripts/data_updates/patch_cypr1_guidance_201023.py @@ -24,5 +24,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_cof_eoi.py b/scripts/fund_round_loaders/load_cof_eoi.py index d53913a7..3d4179f5 100644 --- a/scripts/fund_round_loaders/load_cof_eoi.py +++ b/scripts/fund_round_loaders/load_cof_eoi.py @@ -8,13 +8,13 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("Inserting fund and round data.") insert_fund_data(fund_config) - insert_round_data(round_config_eoi) + upsert_round_data(round_config_eoi) print("Inserting base sections config.") insert_base_sections( @@ -29,5 +29,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_cof_r2.py b/scripts/fund_round_loaders/load_cof_r2.py index 6cee8ea6..85aeb2d8 100644 --- a/scripts/fund_round_loaders/load_cof_r2.py +++ b/scripts/fund_round_loaders/load_cof_r2.py @@ -10,14 +10,14 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: inserted_fund = insert_fund_data(fund_config) print("Fund inserted:") print(inserted_fund) - inserted_rounds = insert_round_data(rounds_config) + inserted_rounds = upsert_round_data(rounds_config) print("Rounds inserted:") print(inserted_rounds) @@ -33,5 +33,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_cof_r3w1.py b/scripts/fund_round_loaders/load_cof_r3w1.py index 556db907..3bc3bd96 100644 --- a/scripts/fund_round_loaders/load_cof_r3w1.py +++ b/scripts/fund_round_loaders/load_cof_r3w1.py @@ -9,13 +9,13 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("Inserting fund and round data.") insert_fund_data(fund_config) - insert_round_data(round_config) + upsert_round_data(round_config) print("Inserting base sections config.") insert_base_sections( @@ -30,5 +30,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_cof_r3w2.py b/scripts/fund_round_loaders/load_cof_r3w2.py index 4e7e827f..e469f4b5 100644 --- a/scripts/fund_round_loaders/load_cof_r3w2.py +++ b/scripts/fund_round_loaders/load_cof_r3w2.py @@ -6,13 +6,13 @@ from config.fund_loader_config.cof.cof_r3 import round_config_w2 from db.queries import insert_base_sections from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("'insert_fund_config(...)' not required as COFR3W2 shares the same fund config from COFR3W1.") print("Inserting round data.") - insert_round_data(round_config_w2) + upsert_round_data(round_config_w2) print("Inserting base sections config.") insert_base_sections( @@ -27,5 +27,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_cof_r3w3.py b/scripts/fund_round_loaders/load_cof_r3w3.py index aac95474..69ab340e 100644 --- a/scripts/fund_round_loaders/load_cof_r3w3.py +++ b/scripts/fund_round_loaders/load_cof_r3w3.py @@ -6,13 +6,13 @@ from config.fund_loader_config.cof.cof_r3 import round_config_w3 from db.queries import insert_base_sections from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("'insert_fund_config(...)' not required as COFR3W3 shares the same fund config from COFR3w1.") print("Inserting round data.") - insert_round_data(round_config_w3) + upsert_round_data(round_config_w3) print("Inserting base sections config.") insert_base_sections( @@ -27,5 +27,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_cof_r4w1.py b/scripts/fund_round_loaders/load_cof_r4w1.py index 1d415133..900b53c4 100644 --- a/scripts/fund_round_loaders/load_cof_r4w1.py +++ b/scripts/fund_round_loaders/load_cof_r4w1.py @@ -8,13 +8,13 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("Inserting fund and round data.") insert_fund_data(fund_config) - insert_round_data(round_config_w1) + upsert_round_data(round_config_w1) print("Inserting base sections config.") insert_base_sections( @@ -29,5 +29,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_cof_r4w2.py b/scripts/fund_round_loaders/load_cof_r4w2.py index 9746bcb3..1bb21150 100644 --- a/scripts/fund_round_loaders/load_cof_r4w2.py +++ b/scripts/fund_round_loaders/load_cof_r4w2.py @@ -6,13 +6,13 @@ from config.fund_loader_config.cof.cof_r4 import round_config_w2 from db.queries import insert_base_sections from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("'insert_fund_config(...)' not required as COFR4W2 shares the same fund config from COFR4w1.") print("Inserting round data.") - insert_round_data(round_config_w2) + upsert_round_data(round_config_w2) print("Inserting base sections config.") insert_base_sections( @@ -27,5 +27,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_cyp_r1.py b/scripts/fund_round_loaders/load_cyp_r1.py index c1c0bcc0..e7bfc7e9 100644 --- a/scripts/fund_round_loaders/load_cyp_r1.py +++ b/scripts/fund_round_loaders/load_cyp_r1.py @@ -9,14 +9,14 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("Inserting fund data for the CYP fund.") insert_fund_data(fund_config) print("Inserting round data for round 1 of the CYP fund.") - insert_round_data(round_config) + upsert_round_data(round_config) print("Inserting base sections for CYP Round 1.") insert_base_sections(APPLICATION_BASE_PATH, ASSESSMENT_BASE_PATH, CYP_ROUND_1_ID) @@ -27,5 +27,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_dpi_r2.py b/scripts/fund_round_loaders/load_dpi_r2.py index 2eaf97fa..5495fed1 100644 --- a/scripts/fund_round_loaders/load_dpi_r2.py +++ b/scripts/fund_round_loaders/load_dpi_r2.py @@ -9,14 +9,14 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("Inserting fund data for the DPI fund.") insert_fund_data(fund_config) print("Inserting round data for round 2 of the DPI fund.") - insert_round_data(round_config) + upsert_round_data(round_config) print("Inserting base sections for DPI Round 2.") insert_base_sections(APPLICATION_BASE_PATH, ASSESSMENT_BASE_PATH, DPI_ROUND_2_ID) @@ -27,5 +27,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_fund_round_from_fab.py b/scripts/fund_round_loaders/load_fund_round_from_fab.py new file mode 100644 index 00000000..dae6e49c --- /dev/null +++ b/scripts/fund_round_loaders/load_fund_round_from_fab.py @@ -0,0 +1,54 @@ +# flake8: noqa +import click + +from config.fund_loader_config.FAB import FAB_FUND_ROUND_CONFIGS +from db import db +from db.queries import insert_base_sections +from db.queries import insert_fund_data +from db.queries import insert_or_update_application_sections +from db.queries import upsert_round_data + + +@click.command() +@click.option("--fund_short_code", default="COF25-EOI", help="Fund short code", prompt=True) +def load_fund_from_fab(fund_short_code) -> None: + """ + Insert the FAB fund and round data into the database. + See required schema for import here: file_location + """ + + FUND_CONFIG = FAB_FUND_ROUND_CONFIGS.get(fund_short_code, None) + if not FUND_CONFIG: + raise ValueError(f"Config for fund {fund_short_code} does not exist") + + if FUND_CONFIG: + print(f"Preparing fund data for the {fund_short_code} fund.") + insert_fund_data(FUND_CONFIG, commit=False) + + for round_short_name, round in FUND_CONFIG["rounds"].items(): + + round_base_path = round["base_path"] + + APPLICATION_BASE_PATH = ".".join([str(round_base_path), str(1)]) + ASSESSMENT_BASE_PATH = ".".join([str(round_base_path), str(2)]) + + print(f"Preparing round data for the '{round_short_name}' round.") + upsert_round_data([round], commit=False) + + # Section config is per round, not per fund + print(f"Preparing base sections for {round_short_name}.") + insert_base_sections(APPLICATION_BASE_PATH, ASSESSMENT_BASE_PATH, round["id"]) + + print(f"Preparing application sections for {round_short_name}.") + insert_or_update_application_sections(round["id"], round["sections_config"]) + + print(f"All config has been successfully prepared, now committing to the database.") + db.session.commit() + print(f"Config has now been committed to the database.") + + +if __name__ == "__main__": + from app import app + + with app.app.app_context(): + load_fund_from_fab() diff --git a/scripts/fund_round_loaders/load_hsra_r1.py b/scripts/fund_round_loaders/load_hsra_r1.py index 7c220ea3..6a5ab843 100644 --- a/scripts/fund_round_loaders/load_hsra_r1.py +++ b/scripts/fund_round_loaders/load_hsra_r1.py @@ -8,13 +8,13 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("Inserting fund and round data for HSRA.") insert_fund_data(fund_config) - insert_round_data(round_config) + upsert_round_data(round_config) print("Inserting base sections config.") insert_base_sections( @@ -29,5 +29,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/scripts/fund_round_loaders/load_ns_r2.py b/scripts/fund_round_loaders/load_ns_r2.py index df9d39e2..111a603a 100644 --- a/scripts/fund_round_loaders/load_ns_r2.py +++ b/scripts/fund_round_loaders/load_ns_r2.py @@ -9,14 +9,14 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def main() -> None: print("Inserting fund data for the Night Shelter fund.") insert_fund_data(fund_config) print("Inserting round data for round 2 of the Night Shelter fund.") - insert_round_data(round_config) + upsert_round_data(round_config) print("Inserting base sections for Night Shelter Round 2.") insert_base_sections(APPLICATION_BASE_PATH, ASSESSMENT_BASE_PATH, NIGHT_SHELTER_ROUND_2_ID) @@ -27,5 +27,5 @@ def main() -> None: if __name__ == "__main__": from app import app - with app.app_context(): + with app.app.app_context(): main() diff --git a/tests/conftest.py b/tests/conftest.py index 42a230f0..69ebb0b8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,8 +15,8 @@ from db.models.round import Round from db.models.section import Section from db.queries import insert_fund_data -from db.queries import insert_round_data from db.queries import insert_sections +from db.queries import upsert_round_data pytest_plugins = ["fsd_test_utils.fixtures.db_fixtures"] @@ -171,7 +171,7 @@ def seed_dynamic_data(request, app, clear_test_data, _db): } rounds.append(round_config) - insert_round_data(rounds) + upsert_round_data(rounds) inserted_data["funds"].append({"rounds": rounds, "id": fund_id, "short_name": fund["short_name"]}) for fund in seed_config["funds"]: diff --git a/tests/test_data/test_fab_round_config.py b/tests/test_data/test_fab_round_config.py new file mode 100644 index 00000000..b2b4ad90 --- /dev/null +++ b/tests/test_data/test_fab_round_config.py @@ -0,0 +1,62 @@ +LOADER_CONFIG = { + "base_path": 0, + "sections_config": [ + {"section_name": {"en": "1. Test Section", "cy": ""}, "tree_path": "0.1.1", "requires_feedback": None}, + { + "section_name": {"en": "1.1 Name your application", "cy": ""}, + "tree_path": "0.1.1.1", + "form_name_json": {"en": "organisation-information", "cy": ""}, + }, + {"section_name": {"en": "2. Test Section 2", "cy": ""}, "tree_path": "0.1.2", "requires_feedback": None}, + { + "section_name": {"en": "2.1 Asset information", "cy": ""}, + "tree_path": "0.1.2.1", + "form_name_json": {"en": "asset-information-cof-r3-w2", "cy": ""}, + }, + ], + "fund_config": { + "id": "b33ea578-b35b-4508-994a-7589a9c9c060", + "short_name": "T", + "welsh_available": False, + "owner_organisation_name": "", + "owner_organisation_shortname": "", + "owner_organisation_logo_uri": "", + "name_json": {"en": "Test"}, + "title_json": {"en": "Test Fund"}, + "description_json": {"en": "test"}, + }, + "round_config": { + "id": "1a2d6043-689b-4472-a09c-fd8fcfd20151", + "fund_id": "b33ea578-b35b-4508-994a-7589a9c9c060", + "short_name": "T", + "opens": "2025-12-12T12:00:00", + "assessment_start": "2026-01-12T12:00:00", + "deadline": "2025-12-24T12:00:00", + "application_reminder_sent": False, + "reminder_date": "2026-01-23T12:00:00", + "assessment_deadline": "2026-01-24T12:00:00", + "prospectus": "https://www.google.com", + "privacy_notice": "https://www.google.com", + "reference_contact_page_over_email": False, + "contact_email": "test@hotmail.com", + "contact_phone": "07555094188", + "contact_textphone": "07555094188", + "support_times": "no", + "support_days": "Mon", + "instructions_json": {"en": "None", "cy": None}, + "feedback_link": "https://www.google.com", + "project_name_field_id": "Test", + "application_guidance_json": {"en": "None", "cy": None}, + "guidance_url": "https://www.google.com", + "all_uploaded_documents_section_available": False, + "application_fields_download_available": False, + "display_logo_on_pdf_exports": False, + "mark_as_complete_enabled": False, + "is_expression_of_interest": False, + "eoi_decision_schema": None, + "feedback_survey_config": "None", + "eligibility_config": {"has_eligibility": False}, + "title_json": {"en": "Tree"}, + "contact_us_banner_json": {"en": "None", "cy": None}, + }, +} diff --git a/tests/test_data_sections.py b/tests/test_data_sections.py index 97ada002..2fe919c0 100644 --- a/tests/test_data_sections.py +++ b/tests/test_data_sections.py @@ -14,7 +14,7 @@ from db.queries import insert_base_sections from db.queries import insert_fund_data from db.queries import insert_or_update_application_sections -from db.queries import insert_round_data +from db.queries import upsert_round_data def test_get_application_sections(seed_dynamic_data): @@ -47,7 +47,7 @@ def test_get_assessment_sections(seed_dynamic_data): def test_load_application_sections(clear_test_data): insert_fund_data(fund_config) - insert_round_data(rounds_config) + upsert_round_data(rounds_config) base_sections = insert_base_sections(APPLICATION_BASE_PATH, ASSESSMENT_BASE_PATH, COF_ROUND_2_WINDOW_2_ID) application_sections = insert_or_update_application_sections(COF_ROUND_2_WINDOW_2_ID, cof_r2_sections)