From 1ec8cf0488e126073ce05de57bdfdd04473a181b Mon Sep 17 00:00:00 2001 From: Jonathan Kerr Date: Sat, 3 Oct 2020 18:30:20 +0100 Subject: [PATCH] Initial attempt at data architecture This commit is the initial design and migration for the data architecture --- app/models.py | 91 +++++++++++++++- .../versions/ebc591cc57f4_first_attempt.py | 101 ++++++++++++++++++ 2 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 migrations/versions/ebc591cc57f4_first_attempt.py diff --git a/app/models.py b/app/models.py index 378f0df..e011c16 100644 --- a/app/models.py +++ b/app/models.py @@ -1,5 +1,94 @@ from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate +from sqlalchemy.ext.declarative import declared_attr +import sqlalchemy as sa -db = SQLAlchemy() migrate = Migrate() + + +class IdModel(object): + @declared_attr + def id(cls): + for base in cls.__mro__[1:-1]: + if getattr(base, "__table__", None) is not None: + type = sa.ForeignKey(base.id) + break + else: + type = sa.Integer + + return sa.Column(type, primary_key=True) + + +db = SQLAlchemy(model_class=IdModel) + + +class NameDescriptionMixin(object): + name = db.Column(db.String(128)) + description = db.Column(db.Text()) + + +class Skill(db.Model, NameDescriptionMixin): + core = db.Column(db.Boolean()) + profession_id = db.Column(db.ForeignKey("profession.id")) + + +class SkillLevel(db.Model): + skill_id = db.Column(db.ForeignKey("skill.id")) + assessment_id = db.Column(db.ForeignKey("assessment.id")) + value = db.Column(db.Integer()) + + +class Profession(db.Model, NameDescriptionMixin): + pass + + +class Role(db.Model): + title = db.Column(db.String(128)) + + profession_id = db.Column(db.ForeignKey("profession.id")) + + +class Posting(db.Model): + candidate_id = db.Column(db.ForeignKey("candidate.id")) + role_id = db.Column(db.ForeignKey("role.id")) + + date_started = db.Column(db.Date()) + date_ended = db.Column(db.Date()) + rotation_number = db.Column(db.Integer()) + + +class Assessment(db.Model): + posting_id = db.Column(db.ForeignKey("posting.id")) + + date = db.Column(db.Date()) + overall_mark = db.Column(db.String(56)) + + posting = db.relationship("Posting") + + def candidate(self): + return Candidate.query.get(self.posting.candidate_id) + + +class Candidate(db.Model): + name = db.Column(db.String(128), nullable=False) + email_address = db.Column(db.String(120), unique=True, nullable=False) + secondary_email_address = db.Column(db.String(120), unique=True) + joining_date = db.Column(db.Date(), nullable=False) + location_restriction = db.Column( + db.Boolean(), default=False, nullable=False + ) # TRUE: yes, FALSE: no, NULL: Prefer not to say + + def __repr__(self): + return f"" + + def update_email(self, new_address: str, primary: bool): + if primary: + self.email_address = new_address + elif not primary: + self.secondary_email_address = new_address + + def current_skill_level(self): + pass + + def latest_assessment(self): + pass diff --git a/migrations/versions/ebc591cc57f4_first_attempt.py b/migrations/versions/ebc591cc57f4_first_attempt.py new file mode 100644 index 0000000..74fb8df --- /dev/null +++ b/migrations/versions/ebc591cc57f4_first_attempt.py @@ -0,0 +1,101 @@ +"""First attempt + +Revision ID: ebc591cc57f4 +Revises: None +Create Date: 2020-10-11 15:22:32.626998 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "ebc591cc57f4" +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "candidate", + sa.Column("name", sa.String(length=128), nullable=False), + sa.Column("email_address", sa.String(length=120), nullable=False), + sa.Column("secondary_email_address", sa.String(length=120), nullable=True), + sa.Column("joining_date", sa.Date(), nullable=False), + sa.Column("location_restriction", sa.Boolean(), nullable=False), + sa.Column("id", sa.Integer(), nullable=False), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("email_address"), + sa.UniqueConstraint("secondary_email_address"), + ) + op.create_table( + "profession", + sa.Column("name", sa.String(length=128), nullable=True), + sa.Column("description", sa.Text(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "role", + sa.Column("title", sa.String(length=128), nullable=True), + sa.Column("profession_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(["profession_id"], ["profession.id"],), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "skill", + sa.Column("name", sa.String(length=128), nullable=True), + sa.Column("description", sa.Text(), nullable=True), + sa.Column("core", sa.Boolean(), nullable=True), + sa.Column("profession_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(["profession_id"], ["profession.id"],), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "posting", + sa.Column("candidate_id", sa.Integer(), nullable=True), + sa.Column("role_id", sa.Integer(), nullable=True), + sa.Column("date_started", sa.Date(), nullable=True), + sa.Column("date_ended", sa.Date(), nullable=True), + sa.Column("rotation_number", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(["candidate_id"], ["candidate.id"],), + sa.ForeignKeyConstraint(["role_id"], ["role.id"],), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "assessment", + sa.Column("posting_id", sa.Integer(), nullable=True), + sa.Column("date", sa.Date(), nullable=True), + sa.Column("overall_mark", sa.String(length=56), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(["posting_id"], ["posting.id"],), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "skill_level", + sa.Column("skill_id", sa.Integer(), nullable=True), + sa.Column("assessment_id", sa.Integer(), nullable=True), + sa.Column("value", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(["assessment_id"], ["assessment.id"],), + sa.ForeignKeyConstraint(["skill_id"], ["skill.id"],), + sa.PrimaryKeyConstraint("id"), + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table("skill_level") + op.drop_table("assessment") + op.drop_table("posting") + op.drop_table("skill") + op.drop_table("role") + op.drop_table("profession") + op.drop_table("candidate") + # ### end Alembic commands ###