Skip to content

Commit

Permalink
PR response
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam-W1 committed Aug 9, 2024
1 parent 1f761bb commit 699278c
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 36 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ Contained in [export_tasks.py](./tasks/export_tasks.py)
The configuration output is generated by the [config_generator](./app/config_generator/README.md) module. This module contains functions to generate fund and round configuration, form JSONs, and HTML representations for a given funding round.

## Database
### Schema
The database schema is defined in [app/db/models.py](./app/db/models.py) and is managed by Alembic. The migrations are stored in [app/db/migrations/versions](./app/db/migrations/versions/)

### Entity Relationship Diagram
See [Here](./app/db/database_ERD_9-8-24.png)

### Recreate Local DBs
For both `DATABASE_URL` and `DATABASE_URL_UNIT_TEST`, drops the database if it exists and then recreates it.

Expand Down
11 changes: 7 additions & 4 deletions app/config_generator/scripts/generate_fund_round_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
from typing import Dict
from typing import Optional

from app.app import app
from flask import current_app

from app.config_generator.scripts.helpers import write_config
from app.db import db
from app.db.models import Form
from app.db.models import Section
from app.db.queries.fund import get_fund_by_id
from app.db.queries.round import get_round_by_id

# TODO : The Round path might be better as a placeholder to avoid conflict in the actual fund store.
# Decide on this further down the line.
ROUND_BASE_PATHS = {
# Should increment for each new round, anything that shares the same base path will also share
# the child tree path config.
Expand Down Expand Up @@ -66,7 +69,7 @@ def generate_application_display_config(round_id):
round_base_path = ROUND_BASE_PATHS[round.short_name]
"sort by Section.index"
sections = db.session.query(Section).filter(Section.round_id == round_id).order_by(Section.index).all()
app.logger.info(f"Generating application display config for round {round_id}")
current_app.logger.info(f"Generating application display config for round {round_id}")

for original_section in sections:
section = copy.deepcopy(original_section)
Expand Down Expand Up @@ -192,7 +195,7 @@ def generate_fund_config(round_id):
round = get_round_by_id(round_id)
fund_id = round.fund_id
fund = get_fund_by_id(fund_id)
app.logger.info(f"Generating fund config for fund {fund_id}")
current_app.logger.info(f"Generating fund config for fund {fund_id}")

fund_export = FundExport(
id=str(fund.fund_id),
Expand All @@ -210,7 +213,7 @@ def generate_fund_config(round_id):

def generate_round_config(round_id):
round = get_round_by_id(round_id)
app.logger.info(f"Generating round config for round {round_id}")
current_app.logger.info(f"Generating round config for round {round_id}")

round_export = RoundExport(
id=str(round.round_id),
Expand Down
93 changes: 87 additions & 6 deletions app/config_generator/scripts/generate_fund_round_form_jsons.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,90 @@
import json

from app.app import app
from flask import current_app

from app.config_generator.generate_form import build_form_json
from app.config_generator.scripts.helpers import validate_json
from app.config_generator.scripts.helpers import write_config
from app.db.queries.round import get_round_by_id

form_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {"type": "string"},
"metadata": {"type": "object"},
"startPage": {"type": "string"},
"backLinkText": {"type": "string"},
"sections": {"type": "array"},
"pages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {"type": "string"},
"title": {"type": "string"},
"components": {
"type": "array",
"items": {
"type": "object",
"properties": {
"options": {
"type": "object",
"properties": {"hideTitle": {"type": "boolean"}, "classes": {"type": "string"}},
},
"type": {"type": "string"},
"title": {"type": "string"},
"hint": {"type": "string"},
"schema": {"type": "object"},
"name": {"type": "string"},
"metadata": {
"type": "object",
},
},
},
},
},
"required": ["path", "title", "components"],
},
},
"lists": {"type": "array"},
"conditions": {"type": "array"},
"fees": {"type": "array"},
"outputs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"title": {"type": "string"},
"type": {"type": "string"},
"outputConfiguration": {
"type": "object",
"properties": {"savePerPageUrl": {"type": "boolean"}},
"required": ["savePerPageUrl"],
},
},
"required": ["name", "title", "type", "outputConfiguration"],
},
},
"skipSummary": {"type": "boolean"},
# Add other top-level keys as needed
},
"required": [
"metadata",
"startPage",
"backLinkText",
"pages",
"lists",
"conditions",
"fees",
"outputs",
"skipSummary",
"name",
"sections",
],
}


def generate_form_jsons_for_round(round_id):
"""
Expand All @@ -22,13 +102,14 @@ def generate_form_jsons_for_round(round_id):
"""
if not round_id:
raise ValueError("Round ID is required to generate form JSONs.")
forms_for_round = []
round = get_round_by_id(round_id)
app.logger.info(f"Generating form JSONs for round {round_id}.")
current_app.logger.info(f"Generating form JSONs for round {round_id}.")
for section in round.sections:
for form in section.forms:
result = build_form_json(form)
form_json = json.dumps(result, indent=4)
forms_for_round.append({"form_name": form.runner_publish_name, "json_str": form_json})
for form in forms_for_round:
write_config(form["json_str"], form["form_name"], round.short_name, "form_json")
valid_json = validate_json(result, form_schema)
if valid_json:
write_config(form_json, form.runner_publish_name, round.short_name, "form_json")
else:
current_app.logger.error(f"Form JSON for {form.runner_publish_name} is invalid.")
5 changes: 3 additions & 2 deletions app/config_generator/scripts/generate_fund_round_html.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from flask import current_app

from app.all_questions.metadata_utils import generate_print_data_for_sections
from app.app import app
from app.config_generator.generate_all_questions import print_html
from app.config_generator.generate_form import build_form_json
from app.config_generator.scripts.helpers import write_config
Expand Down Expand Up @@ -31,7 +32,7 @@ def generate_all_round_html(round_id):
"""
if not round_id:
raise ValueError("Round ID is required to generate HTML.")
app.logger.info(f"Generating HTML for round {round_id}.")
current_app.logger.info(f"Generating HTML for round {round_id}.")
round = get_round_by_id(round_id)
sections_in_round = round.sections
section_data = []
Expand Down
16 changes: 16 additions & 0 deletions app/config_generator/scripts/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
from dataclasses import is_dataclass
from datetime import date

import jsonschema
from flask import current_app
from jsonschema import validate

from app.blueprints.self_serve.routes import human_to_kebab_case
from app.blueprints.self_serve.routes import human_to_snake_case

Expand Down Expand Up @@ -45,3 +49,15 @@ def write_config(config, filename, round_short_name, config_type):
print(content_to_write, file=f) # Print the dictionary for non-JSON types
elif config_type == "html":
f.write(content_to_write)


# Function to validate JSON data against the schema
def validate_json(data, schema):
try:
validate(instance=data, schema=schema)
current_app.logger.info("Given JSON data is valid")
return True
except jsonschema.exceptions.ValidationError as err:
current_app.logger.error("Given JSON data is invalid")
current_app.logger.error(err)
return False
Binary file added app/db/database_ERD_9-8-24.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 18 additions & 16 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.10
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile requirements-dev.in
Expand All @@ -10,6 +10,10 @@ alembic==1.13.2
# via flask-migrate
async-timeout==4.0.3
# via redis
attrs==24.2.0
# via
# jsonschema
# referencing
babel==2.15.0
# via flask-babel
beautifulsoup4==4.12.3
Expand Down Expand Up @@ -67,8 +71,6 @@ editorconfig==0.12.4
# via
# cssbeautifier
# jsbeautifier
exceptiongroup==1.2.2
# via pytest
filelock==3.15.4
# via virtualenv
flake8==7.0.0
Expand Down Expand Up @@ -156,6 +158,10 @@ jsmin==3.0.1
# via -r requirements.in
json5==0.9.25
# via djlint
jsonschema==4.23.0
# via -r requirements.in
jsonschema-specifications==2023.12.1
# via jsonschema
mako==1.3.5
# via alembic
markupsafe==2.1.5
Expand Down Expand Up @@ -210,9 +216,7 @@ pyflakes==3.2.0
pygments==2.18.0
# via rich
pyjwt[crypto]==2.8.0
# via
# funding-service-design-utils
# pyjwt
# via funding-service-design-utils
pyscss==1.4.0
# via -r requirements.in
pytest==8.2.2
Expand Down Expand Up @@ -253,6 +257,10 @@ redis==4.6.0
# via
# flask-redis
# flipper-client
referencing==0.35.1
# via
# jsonschema
# jsonschema-specifications
regex==2023.12.25
# via djlint
requests==2.32.3
Expand All @@ -262,6 +270,10 @@ requests==2.32.3
# python-consul
rich==12.6.0
# via funding-service-design-utils
rpds-py==0.20.0
# via
# jsonschema
# referencing
s3transfer==0.10.2
# via boto3
sentry-sdk[flask]==2.10.0
Expand All @@ -282,7 +294,6 @@ sqlalchemy[mypy]==2.0.31
# alembic
# flask-sqlalchemy
# marshmallow-sqlalchemy
# sqlalchemy
# sqlalchemy-json
# sqlalchemy-utils
sqlalchemy-json==0.7.0
Expand All @@ -293,20 +304,11 @@ sqlalchemy-utils==0.41.2
# funding-service-design-utils
thrift==0.20.0
# via flipper-client
tomli==2.0.1
# via
# black
# djlint
# flake8-pyproject
# mypy
# pytest
# pytest-env
tqdm==4.66.4
# via djlint
typing-extensions==4.12.2
# via
# alembic
# black
# mypy
# sqlalchemy
urllib3==2.2.2
Expand Down
1 change: 1 addition & 0 deletions requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ Flask-WTF==1.2.1
# Utils
#-----------------------------------
funding-service-design-utils>=4.0.1
jsonschema
25 changes: 18 additions & 7 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.10
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile requirements.in
Expand All @@ -10,6 +10,10 @@ alembic==1.13.2
# via flask-migrate
async-timeout==4.0.3
# via redis
attrs==24.2.0
# via
# jsonschema
# referencing
babel==2.15.0
# via flask-babel
beautifulsoup4==4.12.3
Expand Down Expand Up @@ -106,6 +110,10 @@ jmespath==1.0.1
# botocore
jsmin==3.0.1
# via -r requirements.in
jsonschema==4.23.0
# via -r requirements.in
jsonschema-specifications==2023.12.1
# via jsonschema
mako==1.3.5
# via alembic
markupsafe==2.1.5
Expand Down Expand Up @@ -136,9 +144,7 @@ pyee==6.0.0
pygments==2.18.0
# via rich
pyjwt[crypto]==2.8.0
# via
# funding-service-design-utils
# pyjwt
# via funding-service-design-utils
pyscss==1.4.0
# via -r requirements.in
python-consul==1.1.0
Expand All @@ -159,13 +165,21 @@ redis==4.6.0
# via
# flask-redis
# flipper-client
referencing==0.35.1
# via
# jsonschema
# jsonschema-specifications
requests==2.32.3
# via
# -r requirements.in
# funding-service-design-utils
# python-consul
rich==12.6.0
# via funding-service-design-utils
rpds-py==0.20.0
# via
# jsonschema
# referencing
s3transfer==0.10.2
# via boto3
sentry-sdk[flask]==2.10.0
Expand All @@ -184,7 +198,6 @@ sqlalchemy[mypy]==2.0.31
# alembic
# flask-sqlalchemy
# marshmallow-sqlalchemy
# sqlalchemy
# sqlalchemy-json
# sqlalchemy-utils
sqlalchemy-json==0.7.0
Expand All @@ -195,8 +208,6 @@ sqlalchemy-utils==0.41.2
# funding-service-design-utils
thrift==0.20.0
# via flipper-client
tomli==2.0.1
# via mypy
typing-extensions==4.12.2
# via
# alembic
Expand Down
Loading

0 comments on commit 699278c

Please sign in to comment.