diff --git a/api/alembic/versions/3ceec084158f_.py b/api/alembic/versions/3ceec084158f_.py index 858ab251..b5518d1b 100644 --- a/api/alembic/versions/3ceec084158f_.py +++ b/api/alembic/versions/3ceec084158f_.py @@ -7,7 +7,7 @@ """ from alembic import op import sqlalchemy as sa - +from sqlalchemy.engine.reflection import Inspector # revision identifiers, used by Alembic. revision = '3ceec084158f' @@ -15,259 +15,292 @@ branch_labels = None depends_on = None +def create_missing_table(name: str, *create_args) -> bool: + "Create the table if it is not already present in the database." + conn = op.get_bind() + inspector = Inspector.from_engine(conn) + if name not in inspector.get_table_names(): + op.create_table(name, *create_args) + return True + return False def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - op.create_table('applicant_type', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('applicant_type_description', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_applicant_type_id'), 'applicant_type', ['id'], unique=False) - op.create_table('case_status', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('status_description', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_case_status_id'), 'case_status', ['id'], unique=False) - op.create_table('guest_group', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('group_name', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_guest_group_id'), 'guest_group', ['id'], unique=False) - op.create_table('host', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('name', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_host_id'), 'host', ['id'], unique=False) - op.create_table('host_household', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('household_name', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_host_household_id'), 'host_household', ['id'], unique=False) - op.create_table('housing_program_service_provider', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('provider_name', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_housing_program_service_provider_id'), 'housing_program_service_provider', ['id'], unique=False) - op.create_table('image_tag_type', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('tag_text', sa.String(), nullable=False), - sa.Column('tag_description', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_image_tag_type_id'), 'image_tag_type', ['id'], unique=False) - op.create_table('intake_question_type', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('type_description', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_intake_question_type_id'), 'intake_question_type', ['id'], unique=False) - op.create_table('match_status', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('status_description', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_match_status_id'), 'match_status', ['id'], unique=False) - op.create_table('user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('email', sa.String(), nullable=False), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('email') - ) - op.create_index(op.f('ix_user_id'), 'user', ['id'], unique=False) - op.create_table('applicant_status', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('applicant_type', sa.Integer(), nullable=False), - sa.Column('status_description', sa.String(), nullable=False), - sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_applicant_status_id'), 'applicant_status', ['id'], unique=False) - op.create_table('group_match_result', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('guest_group', sa.Integer(), nullable=False), - sa.Column('host_household', sa.Integer(), nullable=False), - sa.Column('match_status', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), - sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), - sa.ForeignKeyConstraint(['match_status'], ['match_status.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_group_match_result_id'), 'group_match_result', ['id'], unique=False) - op.create_table('housing_program', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('program_name', sa.String(), nullable=False), - sa.Column('service_provider', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['service_provider'], ['housing_program_service_provider.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_housing_program_id'), 'housing_program', ['id'], unique=False) - op.create_table('applicant', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('applicant_type', sa.Integer(), nullable=False), - sa.Column('applicant_status', sa.Integer(), nullable=False), - sa.Column('user', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['applicant_status'], ['applicant_status.id'], ), - sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), - sa.ForeignKeyConstraint(['user'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_applicant_id'), 'applicant', ['id'], unique=False) - op.create_table('intake_question_set', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('question_set_name', sa.String(), nullable=False), - sa.Column('housing_program', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_intake_question_set_id'), 'intake_question_set', ['id'], unique=False) - op.create_table('program_coordinator', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('user', sa.Integer(), nullable=False), - sa.Column('housing_program', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), - sa.ForeignKeyConstraint(['user'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_program_coordinator_id'), 'program_coordinator', ['id'], unique=False) - op.create_table('applicant_status_log', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('log_description', sa.String(), nullable=False), - sa.Column('logtime', sa.DateTime(), nullable=False), - sa.Column('applicant', sa.Integer(), nullable=False), - sa.Column('src_status', sa.Integer(), nullable=False), - sa.Column('dest_status', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), - sa.ForeignKeyConstraint(['dest_status'], ['applicant_status.id'], ), - sa.ForeignKeyConstraint(['src_status'], ['applicant_status.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_applicant_status_log_id'), 'applicant_status_log', ['id'], unique=False) - op.create_table('applicant_uploaded_image', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('applicant', sa.Integer(), nullable=False), - sa.Column('image_data', sa.LargeBinary(length=5242880), nullable=False), - sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_applicant_uploaded_image_id'), 'applicant_uploaded_image', ['id'], unique=False) - op.create_table('guest_group_member', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('guest_group', sa.Integer(), nullable=False), - sa.Column('applicant', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), - sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_guest_group_member_id'), 'guest_group_member', ['id'], unique=False) - op.create_table('host_household_member', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('host_household', sa.Integer(), nullable=False), - sa.Column('applicant', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), - sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_host_household_member_id'), 'host_household_member', ['id'], unique=False) - op.create_table('housing_program_pariticipant', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('applicant', sa.Integer(), nullable=False), - sa.Column('housing_program', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), - sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_housing_program_pariticipant_id'), 'housing_program_pariticipant', ['id'], unique=False) - op.create_table('intake_question', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('applicant_type', sa.Integer(), nullable=False), - sa.Column('intake_question_type', sa.Integer(), nullable=False), - sa.Column('intake_question_set', sa.Integer(), nullable=False), - sa.Column('question_text', sa.String(), nullable=False), - sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), - sa.ForeignKeyConstraint(['intake_question_set'], ['intake_question_set.id'], ), - sa.ForeignKeyConstraint(['intake_question_type'], ['intake_question_type.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_intake_question_id'), 'intake_question', ['id'], unique=False) - op.create_table('match_result', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('applicant_a', sa.Integer(), nullable=False), - sa.Column('applicant_b', sa.Integer(), nullable=False), - sa.Column('match_status', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['applicant_a'], ['applicant.id'], ), - sa.ForeignKeyConstraint(['applicant_b'], ['applicant.id'], ), - sa.ForeignKeyConstraint(['match_status'], ['match_status.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_match_result_id'), 'match_result', ['id'], unique=False) - op.create_table('program_case', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('coordinator', sa.Integer(), nullable=False), - sa.Column('case_status', sa.Integer(), nullable=False), - sa.Column('host_household', sa.Integer(), nullable=False), - sa.Column('guest_group', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['case_status'], ['case_status.id'], ), - sa.ForeignKeyConstraint(['coordinator'], ['program_coordinator.id'], ), - sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), - sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_program_case_id'), 'program_case', ['id'], unique=False) - op.create_table('image_tag', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('applicant', sa.Integer(), nullable=False), - sa.Column('image_tag_type', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['applicant'], ['applicant_uploaded_image.id'], ), - sa.ForeignKeyConstraint(['image_tag_type'], ['image_tag_type.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_image_tag_id'), 'image_tag', ['id'], unique=False) - op.create_table('intake_response_value', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('intake_question', sa.Integer(), nullable=False), - sa.Column('response_text', sa.String(), nullable=False), - sa.ForeignKeyConstraint(['intake_question'], ['intake_question.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_intake_response_value_id'), 'intake_response_value', ['id'], unique=False) - op.create_table('program_case_log', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('log_description', sa.String(), nullable=False), - sa.Column('logtime', sa.DateTime(), nullable=False), - sa.Column('program_case', sa.Integer(), nullable=False), - sa.Column('src_status', sa.Integer(), nullable=False), - sa.Column('dest_status', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['dest_status'], ['case_status.id'], ), - sa.ForeignKeyConstraint(['program_case'], ['program_case.id'], ), - sa.ForeignKeyConstraint(['src_status'], ['case_status.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_program_case_log_id'), 'program_case_log', ['id'], unique=False) - op.create_table('match_fail_condition', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('response_value_a', sa.Integer(), nullable=False), - sa.Column('response_value_b', sa.Integer(), nullable=False), - sa.Column('reason_text', sa.String(), nullable=False), - sa.ForeignKeyConstraint(['response_value_a'], ['intake_response_value.id'], ), - sa.ForeignKeyConstraint(['response_value_b'], ['intake_response_value.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_match_fail_condition_id'), 'match_fail_condition', ['id'], unique=False) - op.create_table('match_failure', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('match_result', sa.Integer(), nullable=False), - sa.Column('failed_condition', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['failed_condition'], ['match_fail_condition.id'], ), - sa.ForeignKeyConstraint(['match_result'], ['match_result.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_match_failure_id'), 'match_failure', ['id'], unique=False) + if create_missing_table('applicant_type', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('applicant_type_description', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id')): + op.create_index(op.f('ix_applicant_type_id'), 'applicant_type', ['id'], unique=False) + + if create_missing_table('case_status', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('status_description', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_case_status_id'), 'case_status', ['id'], unique=False) + + if create_missing_table('guest_group', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('group_name', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_guest_group_id'), 'guest_group', ['id'], unique=False) + + if create_missing_table('host', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_host_id'), 'host', ['id'], unique=False) + + if create_missing_table('host_household', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('household_name', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_host_household_id'), 'host_household', ['id'], unique=False) + + if create_missing_table('housing_program_service_provider', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('provider_name', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_housing_program_service_provider_id'), 'housing_program_service_provider', ['id'], unique=False) + + if create_missing_table('image_tag_type', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('tag_text', sa.String(), nullable=False), + sa.Column('tag_description', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_image_tag_type_id'), 'image_tag_type', ['id'], unique=False) + + if create_missing_table('intake_question_type', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('type_description', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_intake_question_type_id'), 'intake_question_type', ['id'], unique=False) + + if create_missing_table('match_status', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('status_description', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_match_status_id'), 'match_status', ['id'], unique=False) + + if create_missing_table('user', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('email', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('email') + ): + op.create_index(op.f('ix_user_id'), 'user', ['id'], unique=False) + + if create_missing_table('applicant_status', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('applicant_type', sa.Integer(), nullable=False), + sa.Column('status_description', sa.String(), nullable=False), + sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_applicant_status_id'), 'applicant_status', ['id'], unique=False) + + if create_missing_table('group_match_result', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('guest_group', sa.Integer(), nullable=False), + sa.Column('host_household', sa.Integer(), nullable=False), + sa.Column('match_status', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), + sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), + sa.ForeignKeyConstraint(['match_status'], ['match_status.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_group_match_result_id'), 'group_match_result', ['id'], unique=False) + + if create_missing_table('housing_program', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('program_name', sa.String(), nullable=False), + sa.Column('service_provider', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['service_provider'], ['housing_program_service_provider.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_housing_program_id'), 'housing_program', ['id'], unique=False) + + if create_missing_table('applicant', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('applicant_type', sa.Integer(), nullable=False), + sa.Column('applicant_status', sa.Integer(), nullable=False), + sa.Column('user', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['applicant_status'], ['applicant_status.id'], ), + sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), + sa.ForeignKeyConstraint(['user'], ['user.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_applicant_id'), 'applicant', ['id'], unique=False) + + if create_missing_table('intake_question_set', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('question_set_name', sa.String(), nullable=False), + sa.Column('housing_program', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_intake_question_set_id'), 'intake_question_set', ['id'], unique=False) + + if create_missing_table('program_coordinator', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('user', sa.Integer(), nullable=False), + sa.Column('housing_program', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), + sa.ForeignKeyConstraint(['user'], ['user.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_program_coordinator_id'), 'program_coordinator', ['id'], unique=False) + + if create_missing_table('applicant_status_log', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('log_description', sa.String(), nullable=False), + sa.Column('logtime', sa.DateTime(), nullable=False), + sa.Column('applicant', sa.Integer(), nullable=False), + sa.Column('src_status', sa.Integer(), nullable=False), + sa.Column('dest_status', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['dest_status'], ['applicant_status.id'], ), + sa.ForeignKeyConstraint(['src_status'], ['applicant_status.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_applicant_status_log_id'), 'applicant_status_log', ['id'], unique=False) + + if create_missing_table('applicant_uploaded_image', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('applicant', sa.Integer(), nullable=False), + sa.Column('image_data', sa.LargeBinary(length=5242880), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_applicant_uploaded_image_id'), 'applicant_uploaded_image', ['id'], unique=False) + + if create_missing_table('guest_group_member', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('guest_group', sa.Integer(), nullable=False), + sa.Column('applicant', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_guest_group_member_id'), 'guest_group_member', ['id'], unique=False) + + if create_missing_table('host_household_member', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('host_household', sa.Integer(), nullable=False), + sa.Column('applicant', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_host_household_member_id'), 'host_household_member', ['id'], unique=False) + + if create_missing_table('housing_program_pariticipant', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('applicant', sa.Integer(), nullable=False), + sa.Column('housing_program', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_housing_program_pariticipant_id'), 'housing_program_pariticipant', ['id'], unique=False) + + if create_missing_table('intake_question', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('applicant_type', sa.Integer(), nullable=False), + sa.Column('intake_question_type', sa.Integer(), nullable=False), + sa.Column('intake_question_set', sa.Integer(), nullable=False), + sa.Column('question_text', sa.String(), nullable=False), + sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), + sa.ForeignKeyConstraint(['intake_question_set'], ['intake_question_set.id'], ), + sa.ForeignKeyConstraint(['intake_question_type'], ['intake_question_type.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_intake_question_id'), 'intake_question', ['id'], unique=False) + + if create_missing_table('match_result', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('applicant_a', sa.Integer(), nullable=False), + sa.Column('applicant_b', sa.Integer(), nullable=False), + sa.Column('match_status', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['applicant_a'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['applicant_b'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['match_status'], ['match_status.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_match_result_id'), 'match_result', ['id'], unique=False) + + if create_missing_table('program_case', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('coordinator', sa.Integer(), nullable=False), + sa.Column('case_status', sa.Integer(), nullable=False), + sa.Column('host_household', sa.Integer(), nullable=False), + sa.Column('guest_group', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['case_status'], ['case_status.id'], ), + sa.ForeignKeyConstraint(['coordinator'], ['program_coordinator.id'], ), + sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), + sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_program_case_id'), 'program_case', ['id'], unique=False) + + if create_missing_table('image_tag', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('applicant', sa.Integer(), nullable=False), + sa.Column('image_tag_type', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant_uploaded_image.id'], ), + sa.ForeignKeyConstraint(['image_tag_type'], ['image_tag_type.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_image_tag_id'), 'image_tag', ['id'], unique=False) + + if create_missing_table('intake_response_value', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('intake_question', sa.Integer(), nullable=False), + sa.Column('response_text', sa.String(), nullable=False), + sa.ForeignKeyConstraint(['intake_question'], ['intake_question.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_intake_response_value_id'), 'intake_response_value', ['id'], unique=False) + + if create_missing_table('program_case_log', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('log_description', sa.String(), nullable=False), + sa.Column('logtime', sa.DateTime(), nullable=False), + sa.Column('program_case', sa.Integer(), nullable=False), + sa.Column('src_status', sa.Integer(), nullable=False), + sa.Column('dest_status', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['dest_status'], ['case_status.id'], ), + sa.ForeignKeyConstraint(['program_case'], ['program_case.id'], ), + sa.ForeignKeyConstraint(['src_status'], ['case_status.id'], ), + sa.PrimaryKeyConstraint('id') + ): + op.create_index(op.f('ix_program_case_log_id'), 'program_case_log', ['id'], unique=False) + + if create_missing_table('match_fail_condition', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('response_value_a', sa.Integer(), nullable=False), + sa.Column('response_value_b', sa.Integer(), nullable=False), + sa.Column('reason_text', sa.String(), nullable=False), + sa.ForeignKeyConstraint(['response_value_a'], ['intake_response_value.id'], ), + sa.ForeignKeyConstraint(['response_value_b'], ['intake_response_value.id'], ), + sa.PrimaryKeyConstraint('id')): + op.create_index(op.f('ix_match_fail_condition_id'), 'match_fail_condition', ['id'], unique=False) + + if create_missing_table('match_failure', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('match_result', sa.Integer(), nullable=False), + sa.Column('failed_condition', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['failed_condition'], ['match_fail_condition.id'], ), + sa.ForeignKeyConstraint(['match_result'], ['match_result.id'], ), + sa.PrimaryKeyConstraint('id')): + op.create_index(op.f('ix_match_failure_id'), 'match_failure', ['id'], unique=False) # ### end Alembic commands ### diff --git a/api/alembic/versions/ec8b1c17739a_drop_unused_tables.py b/api/alembic/versions/ec8b1c17739a_drop_unused_tables.py new file mode 100644 index 00000000..a6713646 --- /dev/null +++ b/api/alembic/versions/ec8b1c17739a_drop_unused_tables.py @@ -0,0 +1,299 @@ +"""Drop unused tables + +Revision ID: ec8b1c17739a +Revises: 3ceec084158f +Create Date: 2024-03-10 15:54:55.578328 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ec8b1c17739a' +down_revision = '3ceec084158f' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index('ix_housing_program_pariticipant_id', table_name='housing_program_pariticipant') + op.drop_table('housing_program_pariticipant') + op.drop_index('ix_applicant_status_id', table_name='applicant_status') + op.drop_table('applicant_status') + op.drop_index('ix_applicant_type_id', table_name='applicant_type') + op.drop_table('applicant_type') + op.drop_index('ix_match_failure_id', table_name='match_failure') + op.drop_table('match_failure') + op.drop_index('ix_program_case_log_id', table_name='program_case_log') + op.drop_table('program_case_log') + op.drop_index('ix_intake_response_value_id', table_name='intake_response_value') + op.drop_table('intake_response_value') + op.drop_index('ix_case_status_id', table_name='case_status') + op.drop_table('case_status') + op.drop_index('ix_image_tag_type_id', table_name='image_tag_type') + op.drop_table('image_tag_type') + op.drop_index('ix_applicant_uploaded_image_id', table_name='applicant_uploaded_image') + op.drop_table('applicant_uploaded_image') + op.drop_index('ix_match_fail_condition_id', table_name='match_fail_condition') + op.drop_table('match_fail_condition') + op.drop_index('ix_host_household_member_id', table_name='host_household_member') + op.drop_table('host_household_member') + op.drop_index('ix_applicant_id', table_name='applicant') + op.drop_table('applicant') + op.drop_index('ix_intake_question_id', table_name='intake_question') + op.drop_table('intake_question') + op.drop_index('ix_image_tag_id', table_name='image_tag') + op.drop_table('image_tag') + op.drop_index('ix_match_status_id', table_name='match_status') + op.drop_table('match_status') + op.drop_index('ix_guest_group_id', table_name='guest_group') + op.drop_table('guest_group') + op.drop_index('ix_applicant_status_log_id', table_name='applicant_status_log') + op.drop_table('applicant_status_log') + op.drop_index('ix_host_household_id', table_name='host_household') + op.drop_table('host_household') + op.drop_index('ix_match_result_id', table_name='match_result') + op.drop_table('match_result') + op.drop_index('ix_intake_question_set_id', table_name='intake_question_set') + op.drop_table('intake_question_set') + op.drop_index('ix_program_case_id', table_name='program_case') + op.drop_table('program_case') + op.drop_index('ix_intake_question_type_id', table_name='intake_question_type') + op.drop_table('intake_question_type') + op.drop_index('ix_guest_group_member_id', table_name='guest_group_member') + op.drop_table('guest_group_member') + op.drop_index('ix_group_match_result_id', table_name='group_match_result') + op.drop_table('group_match_result') + op.drop_index('ix_program_coordinator_id', table_name='program_coordinator') + op.drop_table('program_coordinator') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('program_coordinator', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('user', sa.INTEGER(), nullable=False), + sa.Column('housing_program', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), + sa.ForeignKeyConstraint(['user'], ['user.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_program_coordinator_id', 'program_coordinator', ['id'], unique=False) + op.create_table('group_match_result', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('guest_group', sa.INTEGER(), nullable=False), + sa.Column('host_household', sa.INTEGER(), nullable=False), + sa.Column('match_status', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), + sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), + sa.ForeignKeyConstraint(['match_status'], ['match_status.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_group_match_result_id', 'group_match_result', ['id'], unique=False) + op.create_table('guest_group_member', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('guest_group', sa.INTEGER(), nullable=False), + sa.Column('applicant', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_guest_group_member_id', 'guest_group_member', ['id'], unique=False) + op.create_table('intake_question_type', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('type_description', sa.VARCHAR(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_intake_question_type_id', 'intake_question_type', ['id'], unique=False) + op.create_table('program_case', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('coordinator', sa.INTEGER(), nullable=False), + sa.Column('case_status', sa.INTEGER(), nullable=False), + sa.Column('host_household', sa.INTEGER(), nullable=False), + sa.Column('guest_group', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['case_status'], ['case_status.id'], ), + sa.ForeignKeyConstraint(['coordinator'], ['program_coordinator.id'], ), + sa.ForeignKeyConstraint(['guest_group'], ['guest_group.id'], ), + sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_program_case_id', 'program_case', ['id'], unique=False) + op.create_table('intake_question_set', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('question_set_name', sa.VARCHAR(), nullable=False), + sa.Column('housing_program', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_intake_question_set_id', 'intake_question_set', ['id'], unique=False) + op.create_table('match_result', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('applicant_a', sa.INTEGER(), nullable=False), + sa.Column('applicant_b', sa.INTEGER(), nullable=False), + sa.Column('match_status', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['applicant_a'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['applicant_b'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['match_status'], ['match_status.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_match_result_id', 'match_result', ['id'], unique=False) + op.create_table('host_household', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('household_name', sa.VARCHAR(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_host_household_id', 'host_household', ['id'], unique=False) + op.create_table('applicant_status_log', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('log_description', sa.VARCHAR(), nullable=False), + sa.Column('logtime', sa.DATETIME(), nullable=False), + sa.Column('applicant', sa.INTEGER(), nullable=False), + sa.Column('src_status', sa.INTEGER(), nullable=False), + sa.Column('dest_status', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['dest_status'], ['applicant_status.id'], ), + sa.ForeignKeyConstraint(['src_status'], ['applicant_status.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_applicant_status_log_id', 'applicant_status_log', ['id'], unique=False) + op.create_table('guest_group', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('group_name', sa.VARCHAR(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_guest_group_id', 'guest_group', ['id'], unique=False) + op.create_table('match_status', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('status_description', sa.VARCHAR(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_match_status_id', 'match_status', ['id'], unique=False) + op.create_table('image_tag', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('applicant', sa.INTEGER(), nullable=False), + sa.Column('image_tag_type', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant_uploaded_image.id'], ), + sa.ForeignKeyConstraint(['image_tag_type'], ['image_tag_type.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_image_tag_id', 'image_tag', ['id'], unique=False) + op.create_table('intake_question', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('applicant_type', sa.INTEGER(), nullable=False), + sa.Column('intake_question_type', sa.INTEGER(), nullable=False), + sa.Column('intake_question_set', sa.INTEGER(), nullable=False), + sa.Column('question_text', sa.VARCHAR(), nullable=False), + sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), + sa.ForeignKeyConstraint(['intake_question_set'], ['intake_question_set.id'], ), + sa.ForeignKeyConstraint(['intake_question_type'], ['intake_question_type.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_intake_question_id', 'intake_question', ['id'], unique=False) + op.create_table('applicant', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('applicant_type', sa.INTEGER(), nullable=False), + sa.Column('applicant_status', sa.INTEGER(), nullable=False), + sa.Column('user', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['applicant_status'], ['applicant_status.id'], ), + sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), + sa.ForeignKeyConstraint(['user'], ['user.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_applicant_id', 'applicant', ['id'], unique=False) + op.create_table('host_household_member', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('host_household', sa.INTEGER(), nullable=False), + sa.Column('applicant', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['host_household'], ['host_household.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_host_household_member_id', 'host_household_member', ['id'], unique=False) + op.create_table('match_fail_condition', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('response_value_a', sa.INTEGER(), nullable=False), + sa.Column('response_value_b', sa.INTEGER(), nullable=False), + sa.Column('reason_text', sa.VARCHAR(), nullable=False), + sa.ForeignKeyConstraint(['response_value_a'], ['intake_response_value.id'], ), + sa.ForeignKeyConstraint(['response_value_b'], ['intake_response_value.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_match_fail_condition_id', 'match_fail_condition', ['id'], unique=False) + op.create_table('applicant_uploaded_image', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('applicant', sa.INTEGER(), nullable=False), + sa.Column('image_data', sa.BLOB(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_applicant_uploaded_image_id', 'applicant_uploaded_image', ['id'], unique=False) + op.create_table('image_tag_type', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('tag_text', sa.VARCHAR(), nullable=False), + sa.Column('tag_description', sa.VARCHAR(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_image_tag_type_id', 'image_tag_type', ['id'], unique=False) + op.create_table('case_status', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('status_description', sa.VARCHAR(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_case_status_id', 'case_status', ['id'], unique=False) + op.create_table('intake_response_value', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('intake_question', sa.INTEGER(), nullable=False), + sa.Column('response_text', sa.VARCHAR(), nullable=False), + sa.ForeignKeyConstraint(['intake_question'], ['intake_question.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_intake_response_value_id', 'intake_response_value', ['id'], unique=False) + op.create_table('program_case_log', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('log_description', sa.VARCHAR(), nullable=False), + sa.Column('logtime', sa.DATETIME(), nullable=False), + sa.Column('program_case', sa.INTEGER(), nullable=False), + sa.Column('src_status', sa.INTEGER(), nullable=False), + sa.Column('dest_status', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['dest_status'], ['case_status.id'], ), + sa.ForeignKeyConstraint(['program_case'], ['program_case.id'], ), + sa.ForeignKeyConstraint(['src_status'], ['case_status.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_program_case_log_id', 'program_case_log', ['id'], unique=False) + op.create_table('match_failure', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('match_result', sa.INTEGER(), nullable=False), + sa.Column('failed_condition', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['failed_condition'], ['match_fail_condition.id'], ), + sa.ForeignKeyConstraint(['match_result'], ['match_result.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_match_failure_id', 'match_failure', ['id'], unique=False) + op.create_table('applicant_type', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('applicant_type_description', sa.VARCHAR(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_applicant_type_id', 'applicant_type', ['id'], unique=False) + op.create_table('applicant_status', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('applicant_type', sa.INTEGER(), nullable=False), + sa.Column('status_description', sa.VARCHAR(), nullable=False), + sa.ForeignKeyConstraint(['applicant_type'], ['applicant_type.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_applicant_status_id', 'applicant_status', ['id'], unique=False) + op.create_table('housing_program_pariticipant', + sa.Column('id', sa.INTEGER(), nullable=False), + sa.Column('applicant', sa.INTEGER(), nullable=False), + sa.Column('housing_program', sa.INTEGER(), nullable=False), + sa.ForeignKeyConstraint(['applicant'], ['applicant.id'], ), + sa.ForeignKeyConstraint(['housing_program'], ['housing_program.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index('ix_housing_program_pariticipant_id', 'housing_program_pariticipant', ['id'], unique=False) + # ### end Alembic commands ### diff --git a/api/openapi_server/models/README.md b/api/openapi_server/models/README.md new file mode 100644 index 00000000..5da25e61 --- /dev/null +++ b/api/openapi_server/models/README.md @@ -0,0 +1,60 @@ +# Data Model + +```mermaid +classDiagram +class alembic_version{ + *VARCHAR<32> version_num NOT NULL +} +class host{ + *INTEGER id NOT NULL + VARCHAR name NOT NULL +} +class housing_program{ + *INTEGER id NOT NULL + VARCHAR program_name NOT NULL + INTEGER service_provider NOT NULL +} +class housing_program_service_provider{ + *INTEGER id NOT NULL + VARCHAR provider_name NOT NULL +} +class user{ + *INTEGER id NOT NULL + VARCHAR email NOT NULL +} +housing_program_service_provider "1" -- "0..n" housing_program +``` + +## Data Model Generation + +Our data model is autogenerated using `eralchemy2`. The `eralchemy2` tool relies on `pygraphviz` and `graphviz` which are not easily installed using pip. The tool is easier to install on linux than windows, but instructions are provided for both operating systems. + +### Linux Install + +```bash +sudo apt install graphviz libgraphviz-dev pkg-config +python3 -m pip install pygraphviz +python3 -m pip install eralchemy2 +``` + +### Windows Install + +```pwsh +# If you don't have the choco package manager then +# exe installers are available https://graphviz.org/download/ +choco install graphviz +python -m pip install --use-pep517 ` + --config-settings="--global-option=build_ext" ` + --config-settings="--global-option="-IC:\Program Files\Graphviz\include" ` + --config-settings="--global-option="-LC:\Program Files\Graphviz\lib" ` + pygraphviz +python -m pip install eralchemy2 +``` + +### Model Generation + +Once `eralchemy2` is installed, you can generate the ER diagram using these commands. + +```shell +eralchemy2 -i "sqlite:///./homeuniteus.db" -o "HomeUniteUsDataModel.md" +``` diff --git a/api/openapi_server/models/database.py b/api/openapi_server/models/database.py index f9e07369..c604f2ca 100644 --- a/api/openapi_server/models/database.py +++ b/api/openapi_server/models/database.py @@ -1,7 +1,7 @@ from sqlalchemy import create_engine from sqlalchemy.engine import Engine from sqlalchemy.orm import Session, declarative_base -from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, LargeBinary +from sqlalchemy import Column, Integer, String, ForeignKey Base = declarative_base() @@ -10,133 +10,6 @@ class User(Base): id = Column(Integer, primary_key=True, index=True) email = Column(String, nullable=False, unique=True) - -class ApplicantType(Base): - __tablename__ = "applicant_type" - - id = Column(Integer, primary_key=True, index=True) - applicant_type_description = Column(String, nullable=False) - - -class ApplicantStatus(Base): - __tablename__ = "applicant_status" - - id = Column(Integer, primary_key=True, index=True) - applicant_type = Column(Integer, ForeignKey('applicant_type.id'), nullable=False) - status_description = Column(String, nullable=False) - - -class Applicant(Base): - __tablename__ = "applicant" - - id = Column(Integer, primary_key=True, index=True) - applicant_type = Column(Integer, ForeignKey('applicant_type.id'), nullable=False) - applicant_status = Column(Integer, ForeignKey('applicant_status.id'), nullable=False) - user = Column(Integer, ForeignKey('user.id'), nullable=False) - - -class ApplicantStatusLog(Base): - __tablename__ = "applicant_status_log" - id = Column(Integer, primary_key=True, index=True) - log_description = Column(String, nullable=False) - logtime = Column(DateTime, nullable=False) - applicant = Column(Integer, ForeignKey('applicant.id'), nullable=False) - src_status = Column(Integer, ForeignKey('applicant_status.id'), nullable=False) - dest_status = Column(Integer, ForeignKey('applicant_status.id'), nullable=False) - - -class IntakeQuestionType(Base): - __tablename__ = "intake_question_type" - - id = Column(Integer, primary_key=True, index=True) - type_description = Column(String, nullable=False) - - -class IntakeQuestion(Base): - __tablename__ = "intake_question" - - id = Column(Integer, primary_key=True, index=True) - applicant_type = Column(Integer, ForeignKey('applicant_type.id'), nullable=False) - intake_question_type = Column(Integer, ForeignKey('intake_question_type.id'), nullable=False) - intake_question_set = Column(Integer, ForeignKey('intake_question_set.id'), nullable=False) - question_text = Column(String, nullable=False) - - -class IntakeResponseValue(Base): - __tablename__ = "intake_response_value" - - id = Column(Integer, primary_key=True, index=True) - - intake_question = Column(Integer, ForeignKey('intake_question.id'), nullable=False) - response_text = Column(String, nullable=False) - - -class MatchFailCondition(Base): - __tablename__ = "match_fail_condition" - - id = Column(Integer, primary_key=True, index=True) - - response_value_a = Column(Integer, ForeignKey('intake_response_value.id'), nullable=False) - response_value_b = Column(Integer, ForeignKey('intake_response_value.id'), nullable=False) - reason_text = Column(String, nullable=False) - - -class MatchStatus(Base): - __tablename__ = "match_status" - - id = Column(Integer, primary_key=True, index=True) - status_description = Column(String, nullable=False) - - -class ApplicantUploadedImage(Base): - __tablename__ = "applicant_uploaded_image" - - id = Column(Integer, primary_key=True, index=True) - applicant = Column(Integer, ForeignKey('applicant.id'), nullable=False) - image_data = Column(LargeBinary(length=5242880), nullable=False) - - -class ApplicantUploadedImageTag(Base): - __tablename__ = "image_tag" - - id = Column(Integer, primary_key=True, index=True) - applicant = Column(Integer, ForeignKey('applicant_uploaded_image.id'), nullable=False) - image_tag_type = Column(Integer, ForeignKey('image_tag_type.id'), nullable=False) - - -class ImageTagType(Base): - __tablename__ = "image_tag_type" - - id = Column(Integer, primary_key=True, index=True) - tag_text = Column(String, nullable=False) - tag_description = Column(String, nullable=False) - - -class MatchResult(Base): - __tablename__ = "match_result" - - id = Column(Integer, primary_key=True, index=True) - applicant_a = Column(Integer, ForeignKey('applicant.id'), nullable=False) - applicant_b = Column(Integer, ForeignKey('applicant.id'), nullable=False) - match_status = Column(Integer, ForeignKey('match_status.id'), nullable=False) - - -class GroupMatchResult(Base): - __tablename__ = "group_match_result" - - id = Column(Integer, primary_key=True, index=True) - guest_group = Column(Integer, ForeignKey('guest_group.id'), nullable=False) - host_household = Column(Integer, ForeignKey('host_household.id'), nullable=False) - match_status = Column(Integer, ForeignKey('match_status.id'), nullable=False) - - -class MatchFailure(Base): - __tablename__ = "match_failure" - - id = Column(Integer, primary_key=True, index=True) - match_result = Column(Integer, ForeignKey('match_result.id'), nullable=False) - failed_condition = Column(Integer, ForeignKey('match_fail_condition.id'), nullable=False) - class HousingProgramServiceProvider(Base): __tablename__ = "housing_program_service_provider" @@ -153,86 +26,11 @@ class HousingProgram(Base): program_name = Column(String, nullable=False) service_provider = Column(Integer, ForeignKey('housing_program_service_provider.id'), nullable=False) -class IntakeQuestionSet(Base): - __tablename__ = "intake_question_set" - - id = Column(Integer, primary_key=True, index=True) - question_set_name = Column(String, nullable=False) - housing_program = Column(Integer, ForeignKey('housing_program.id'), nullable=False) - - -class ProgramParticipant(Base): - __tablename__ = "housing_program_pariticipant" - - id = Column(Integer, primary_key=True, index=True) - applicant = Column(Integer, ForeignKey('applicant.id'), nullable=False) - housing_program = Column(Integer, ForeignKey('housing_program.id'), nullable=False) - - -class ProgramCoordinator(Base): - __tablename__ = "program_coordinator" - - id = Column(Integer, primary_key=True, index=True) - user = Column(Integer, ForeignKey('user.id'), nullable=False) - housing_program = Column(Integer, ForeignKey('housing_program.id'), nullable=False) - - -class GuestGroup(Base): - __tablename__ = "guest_group" - - id = Column(Integer, primary_key=True, index=True) - group_name = Column(String, nullable=False) - -class GuestGroupMember(Base): - __tablename__ = "guest_group_member" - - id = Column(Integer, primary_key=True, index=True) - - guest_group = Column(Integer, ForeignKey('guest_group.id'), nullable=False) - applicant = Column(Integer, ForeignKey('applicant.id'), nullable=False) - class Host(Base): __tablename__ = "host" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) -class HostHousehold(Base): - __tablename__ = "host_household" - - id = Column(Integer, primary_key=True, index=True) - household_name = Column(String, nullable=False) - -class HostHouseholdMember(Base): - __tablename__ = "host_household_member" - - id = Column(Integer, primary_key=True, index=True) - host_household = Column(Integer, ForeignKey('host_household.id'), nullable=False) - applicant = Column(Integer, ForeignKey('applicant.id'), nullable=False) - -class CaseStatus(Base): - __tablename__ = "case_status" - - id = Column(Integer, primary_key=True, index=True) - status_description = Column(String, nullable=False) - -class ProgramCase(Base): - __tablename__ = "program_case" - - id = Column(Integer, primary_key=True, index=True) - coordinator = Column(Integer, ForeignKey('program_coordinator.id'), nullable=False) - case_status = Column(Integer, ForeignKey('case_status.id'), nullable=False) - host_household = Column(Integer, ForeignKey('host_household.id'), nullable=False) - guest_group = Column(Integer, ForeignKey('guest_group.id'), nullable=False) - -class ProgramCaseStatusLog(Base): - __tablename__ = "program_case_log" - - id = Column(Integer, primary_key=True, index=True) - log_description = Column(String, nullable=False) - logtime = Column(DateTime, nullable=False) - program_case = Column(Integer, ForeignKey('program_case.id'), nullable=False) - src_status = Column(Integer, ForeignKey('case_status.id'), nullable=False) - dest_status = Column(Integer, ForeignKey('case_status.id'), nullable=False) class DataAccessLayer: _engine: Engine = None diff --git a/api/openapi_server/models/schema.py b/api/openapi_server/models/schema.py index 5c534e2a..092e532d 100644 --- a/api/openapi_server/models/schema.py +++ b/api/openapi_server/models/schema.py @@ -2,119 +2,12 @@ from openapi_server.models.database import * - class UserSchema(SQLAlchemyAutoSchema): class Meta: model = User include_relationships = True load_instance = True - -class ApplicantTypeSchema(SQLAlchemyAutoSchema): - class Meta: - model = ApplicantType - include_relationships = True - load_instance = True - - -class ApplicantStatusSchema(SQLAlchemyAutoSchema): - class Meta: - model = ApplicantStatus - include_relationships = True - load_instance = True - - -class ApplicantSchema(SQLAlchemyAutoSchema): - class Meta: - model = Applicant - include_relationships = True - load_instance = True - - -class ApplicantStatusLogSchema(SQLAlchemyAutoSchema): - class Meta: - model = ApplicantStatusLog - include_relationships = True - load_instance = True - - -class IntakeQuestionTypeSchema(SQLAlchemyAutoSchema): - class Meta: - model = IntakeQuestionType - include_relationships = True - load_instance = True - - -class IntakeQuestionSchema(SQLAlchemyAutoSchema): - class Meta: - model = IntakeQuestion - include_relationships = True - load_instance = True - - -class IntakeResponseValueSchema(SQLAlchemyAutoSchema): - class Meta: - model = IntakeResponseValue - include_relationships = True - load_instance = True - - -class MatchFailConditionSchema(SQLAlchemyAutoSchema): - class Meta: - model = MatchFailCondition - include_relationships = True - load_instance = True - - -class MatchStatusSchema(SQLAlchemyAutoSchema): - class Meta: - model = MatchStatus - include_relationships = True - load_instance = True - - -class ApplicantUploadedImageSchema(SQLAlchemyAutoSchema): - class Meta: - model = ApplicantUploadedImage - include_relationships = True - load_instance = True - - -class ApplicantUploadedImageTagSchema(SQLAlchemyAutoSchema): - class Meta: - model = ApplicantUploadedImageTag - include_relationships = True - load_instance = True - - -class ImageTagTypeSchema(SQLAlchemyAutoSchema): - class Meta: - model = ImageTagType - include_relationships = True - load_instance = True - - -class MatchResultSchema(SQLAlchemyAutoSchema): - class Meta: - model = MatchResult - include_relationships = True - load_instance = True - - -class GroupMatchResultSchema(SQLAlchemyAutoSchema): - class Meta: - model = GroupMatchResult - include_relationships = True - load_instance = True - - -class MatchFailureSchema(SQLAlchemyAutoSchema): - class Meta: - model = MatchFailure - include_relationships = True - load_instance = True - - class HousingProgramServiceProviderSchema(SQLAlchemyAutoSchema): class Meta: model = HousingProgramServiceProvider @@ -128,83 +21,12 @@ class Meta: include_relationships = True load_instance = True - -class IntakeQuestionSetSchema(SQLAlchemyAutoSchema): - class Meta: - model = IntakeQuestionSet - include_relationships = True - load_instance = True - - -class ProgramParticipantSchema(SQLAlchemyAutoSchema): - class Meta: - model = ProgramParticipant - include_relationships = True - load_instance = True - - -class ProgramCoordinatorSchema(SQLAlchemyAutoSchema): - class Meta: - model = ProgramCoordinator - include_relationships = True - load_instance = True - - -class GuestGroupSchema(SQLAlchemyAutoSchema): - class Meta: - model = GuestGroup - include_relationships = True - load_instance = True - - -class GuestGroupMemberSchema(SQLAlchemyAutoSchema): - class Meta: - model = GuestGroupMember - include_relationships = True - load_instance = True - - class HostSchema(SQLAlchemyAutoSchema): class Meta: model = Host include_relationships = True load_instance = True - -class HostHouseholdSchema(SQLAlchemyAutoSchema): - class Meta: - model = HostHousehold - include_relationships = True - load_instance = True - - -class HostHouseholdMemberSchema(SQLAlchemyAutoSchema): - class Meta: - model = HostHouseholdMember - include_relationships = True - load_instance = True - - -class CaseStatusSchema(SQLAlchemyAutoSchema): - class Meta: - model = CaseStatus - include_relationships = True - load_instance = True - - -class ProgramCaseSchema(SQLAlchemyAutoSchema): - class Meta: - model = ProgramCase - include_relationships = True - load_instance = True - - -class ProgramCaseStatusLogSchema(SQLAlchemyAutoSchema): - class Meta: - model = ProgramCaseStatusLog - include_relationships = True - load_instance = True - host_schema = HostSchema() hosts_schema = HostSchema(many=True) service_provider_schema = HousingProgramServiceProviderSchema() diff --git a/api/openapi_server/openapi/schemas/_index.yaml b/api/openapi_server/openapi/schemas/_index.yaml index 01440bd0..e8ee251f 100644 --- a/api/openapi_server/openapi/schemas/_index.yaml +++ b/api/openapi_server/openapi/schemas/_index.yaml @@ -16,14 +16,6 @@ ApiResponse: type: string title: ApiResponse type: object -ApplicantType: - type: object - properties: - applicant_type_description: - title: applicant_type_description - type: string - required: - - applicant_type_description HousingProgram: type: object properties: @@ -57,53 +49,6 @@ ServiceProviders: type: array items: $ref: '#/ServiceProviderWithId' -IntakeQuestion: - type: object - properties: - applicant_type: - $ref: '#/ApplicantType' - question_text: - title: question_text - type: string - intake_question_type: - $ref: '#/IntakeQuestionType' - intake_question_set: - $ref: '#/IntakeQuestionSet' - required: - - applicant_type - - question_text - - intake_question_type - - intake_question_set -IntakeQuestionSet: - type: object - properties: - question_set_name: - title: question_set_name - type: string - housing_program: - $ref: '#/HousingProgram' - required: - - question_set_name - - housing_program -IntakeQuestionType: - type: object - properties: - type_description: - title: type_description - type: string - required: - - type_description -IntakeResponseValue: - type: object - properties: - response_text: - title: response_text - type: string - intake_question: - $ref: '#/IntakeQuestion' - required: - - response_text - - intake_question HostResponse: type: object properties: diff --git a/api/pyproject.toml b/api/pyproject.toml index c0d5a0a0..ff20a62a 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -97,7 +97,7 @@ dependencies = [ # marshmallow is used to define database model schema, to enable easy serialization # of models to and from json. "marshmallow==3.20.1", - "marshmallow_sqlalchemy==0.30.0", + "marshmallow_sqlalchemy==1.0.0", "openapi-spec-validator==0.6.0", ] diff --git a/api/requirements-dev.txt b/api/requirements-dev.txt index 249a02ae..5a261c4d 100644 --- a/api/requirements-dev.txt +++ b/api/requirements-dev.txt @@ -47,9 +47,13 @@ colorama==0.4.6 # pytest # tox connexion==2.14.2 - # via homeuniteus-api (pyproject.toml) + # via + # connexion + # homeuniteus-api (pyproject.toml) coverage==7.3.0 - # via pytest-cov + # via + # coverage + # pytest-cov cryptography==41.0.7 # via # moto @@ -110,10 +114,13 @@ markupsafe==2.1.3 # mako # werkzeug marshmallow==3.20.1 + # via + # homeuniteus-api (pyproject.toml) + # marshmallow-sqlalchemy +marshmallow-sqlalchemy==1.0.0 # via homeuniteus-api (pyproject.toml) moto==4.2.10 # via homeuniteus-api (pyproject.toml) -marshmallow_sqlalchemy==0.30.0 openapi-schema-validator==0.6.0 # via openapi-spec-validator openapi-spec-validator==0.6.0 @@ -169,7 +176,9 @@ python-dateutil==2.8.2 python-dotenv==0.20.0 # via homeuniteus-api (pyproject.toml) python-jose==3.3.0 - # via moto + # via + # moto + # python-jose pyyaml==6.0.1 # via # clickclick @@ -211,7 +220,9 @@ six==1.16.0 # python-dateutil # rfc3339-validator sqlalchemy==2.0.20 - # via alembic + # via + # alembic + # marshmallow-sqlalchemy swagger-ui-bundle==0.0.9 # via connexion tomli==2.0.1 diff --git a/api/requirements.txt b/api/requirements.txt index 82e96859..f58a37a3 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -78,7 +78,7 @@ marshmallow==3.20.1 # via # homeuniteus-api (pyproject.toml) # marshmallow-sqlalchemy -marshmallow-sqlalchemy==0.30.0 +marshmallow-sqlalchemy==1.0.0 # via homeuniteus-api (pyproject.toml) openapi-schema-validator==0.6.0 # via openapi-spec-validator @@ -88,7 +88,6 @@ packaging==23.1 # via # connexion # marshmallow - # marshmallow-sqlalchemy # prance pathable==0.4.3 # via jsonschema-spec diff --git a/api/tests/test_schema.py b/api/tests/test_schema.py index e1b64eab..f5986a95 100644 --- a/api/tests/test_schema.py +++ b/api/tests/test_schema.py @@ -1,9 +1,11 @@ import json +import pytest +from marshmallow.exceptions import ValidationError -from openapi_server.models.schema import HostSchema, HousingProgramServiceProviderSchema +from openapi_server.models.schema import HostSchema, host_schema, hosts_schema, HousingProgramServiceProviderSchema +from openapi_server.models.database import Host, DataAccessLayer - -def test_create_host(client): +def test_create_host(): test_host_string = "{\"id\": 5, \"name\": \"test\"}" test_host = HostSchema(many=True) @@ -22,7 +24,7 @@ def test_create_host(client): assert jsonresult == test_host_string, "HostSchema json did not match test string " -def test_housing_program_service_provider(client): +def test_housing_program_service_provider(): test_housing_program_service_provide_string = "{\"id\": 5, \"provider_name\": \"test\"}" housing_program_service_provider = HousingProgramServiceProviderSchema(many=True) @@ -39,3 +41,80 @@ def test_housing_program_service_provider(client): jsonresult = json.dumps(housing_program_service_provider.fields) assert jsonresult == test_housing_program_service_provide_string, "HousingProgramServiceProvider json did not match test string " + +def test_deserialize_fromjson(client): + ''' + Verify that the host schema can be deserialized from json. + ''' + json_from_request ='{"id": 1, "name": "Josh"}' + host = host_schema.load(json.loads(json_from_request), session=DataAccessLayer.session()) + + assert host is not None, "Host is null" + assert isinstance(host, Host), "host is not of type Host" + assert host.id == 1, "Host id did not match what was input" + assert host.name == "Josh", "Host name did not match what was input" + +def test_serialize_tojson(): + ''' + Verify that the host schema can be serialized to json. + ''' + host_to_respond_with = Host(id=1, name="Josh") + json_from_host = host_schema.dump(host_to_respond_with) + assert json_from_host is not None, "Json from host is null" + assert json_from_host['id'] == 1, "Json from host id did not match what was input" + assert json_from_host['name'] == "Josh", "Json from host name did not match what was input" + +def test_deserialize_multiplehost(client): + ''' + Verify that the host schema can be deserialized from multiple hosts. + ''' + json_from_request = '[{"id": 1, "name": "Josh"}, {"id": 2, "name": "John"}]' + hosts = hosts_schema.load(json.loads(json_from_request), session=DataAccessLayer.session()) + assert hosts is not None, "Hosts is null" + assert len(hosts) == 2, "Hosts length did not match what was input" + assert isinstance(hosts[0], Host), "Hosts is not of type Host" + assert hosts[0].id == 1, "Hosts id did not match what was input" + assert hosts[0].name == "Josh", "Hosts name did not match what was input" + assert hosts[1].id == 2, "Hosts id did not match what was input" + assert hosts[1].name == "John", "Hosts name did not match what was input" + +def test_serialize_multiplehost(): + ''' + Verify that the host schema can be serialized to multiple hosts. + ''' + hosts_to_respond_with = [Host(id=1, name="Josh"), Host(id=2, name="John")] + json_from_hosts = hosts_schema.dump(hosts_to_respond_with) + + assert json_from_hosts is not None, "Json from hosts is null" + assert len(json_from_hosts) == 2, "Json from hosts length did not match what was input" + assert json_from_hosts[0]['id'] == 1, "Json from hosts id did not match what was input" + assert json_from_hosts[0]['name'] == "Josh", "Json from hosts name did not match what was input" + assert json_from_hosts[1]['id'] == 2, "Json from hosts id did not match what was input" + assert json_from_hosts[1]['name'] == "John", "Json from hosts name did not match what was input" + +def test_deserializejson_extrafield_error(client): + ''' + Verify that json with extra fields will raise a validation error. + ''' + json_from_request ='{"id": 1, "name": "Josh", "extra_field": "extra"}' + data_from_request = json.loads(json_from_request) + with pytest.raises(ValidationError): + host_schema.load(data_from_request, session=DataAccessLayer.session()) + +def test_deserializejson_missingfield_error(client): + ''' + Verify that json with a missing field will raise a validation error. + ''' + json_from_request ='{"id": 1}' + data_from_request = json.loads(json_from_request) + with pytest.raises(ValidationError): + host_schema.load(data_from_request, session=DataAccessLayer.session()) + +def test_deserializejson_missingindex_noerror(client): + ''' + Verify that json with a missing id will not raise a validation error. + ''' + json_from_request ='{"name": "Josh"}' + data_from_request = json.loads(json_from_request) + host = host_schema.load(data_from_request, session=DataAccessLayer.session()) + assert host.id == None, "Host id is not null" \ No newline at end of file