2021-03-18 13:53:55 +00:00
|
|
|
"""
|
|
|
|
See the file DB.drawio for the design of the database. It can be opened in the internet browser with the website:
|
|
|
|
https://app.diagrams.net
|
|
|
|
|
|
|
|
For more information about the implementation, see the part to Models in the documentation of Flask-SQLAlchemy:
|
|
|
|
https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/
|
|
|
|
"""
|
|
|
|
|
2021-04-03 00:11:26 +00:00
|
|
|
# Imports
|
2021-06-10 01:14:30 +00:00
|
|
|
from flask import flash
|
2021-06-02 21:43:41 +00:00
|
|
|
from flask_security.models.fsqla_v2 import FsRoleMixin, FsUserMixin
|
2021-04-03 00:11:26 +00:00
|
|
|
|
2021-03-18 13:53:55 +00:00
|
|
|
# Importing the database instance
|
|
|
|
from advlabdb import db
|
2021-06-01 23:56:49 +00:00
|
|
|
from advlabdb.configUtils import getConfig
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Student(db.Model):
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
student_number = db.Column(db.Integer, nullable=False, unique=True)
|
|
|
|
first_name = db.Column(db.String(100), nullable=False)
|
|
|
|
last_name = db.Column(db.String(100), nullable=False)
|
2021-05-14 16:53:15 +00:00
|
|
|
uni_email = db.Column(db.String(200), nullable=False, unique=True)
|
|
|
|
contact_email = db.Column(db.String(200), unique=True)
|
2021-03-18 13:53:55 +00:00
|
|
|
bachelor_thesis = db.Column(db.String, nullable=True)
|
|
|
|
bachelor_thesis_work_group = db.Column(db.String, nullable=True)
|
|
|
|
note = db.Column(db.Text, nullable=True)
|
|
|
|
part_students = db.relationship("PartStudent", backref="student", lazy=True)
|
|
|
|
|
2021-04-24 10:05:58 +00:00
|
|
|
def __repr__(self):
|
2021-04-24 11:38:03 +00:00
|
|
|
return f"<Student: {self.first_name} {self.last_name}>"
|
2021-04-24 10:05:58 +00:00
|
|
|
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
class PartStudent(db.Model):
|
|
|
|
# A student doing a specific part
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
final_part_mark = db.Column(db.Integer, nullable=True)
|
|
|
|
student_id = db.Column(db.Integer, db.ForeignKey("student.id"), nullable=False)
|
|
|
|
part_id = db.Column(db.Integer, db.ForeignKey("part.id"), nullable=False)
|
|
|
|
group_id = db.Column(db.Integer, db.ForeignKey("group.id"), nullable=True)
|
|
|
|
experiment_marks = db.relationship("ExperimentMark", backref="part_student", lazy=True)
|
|
|
|
|
|
|
|
|
|
|
|
class Group(db.Model):
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
number = db.Column(db.Integer, nullable=False)
|
2021-03-19 20:15:43 +00:00
|
|
|
part_id = db.Column(db.Integer, db.ForeignKey("part.id"), nullable=False)
|
2021-03-18 13:53:55 +00:00
|
|
|
part_students = db.relationship("PartStudent", backref="group", lazy=True)
|
|
|
|
group_experiments = db.relationship("GroupExperiment", backref="group", lazy=True)
|
|
|
|
|
2021-04-24 11:38:03 +00:00
|
|
|
def __repr__(self):
|
|
|
|
return f"<Group {self.number} {Part.query.get(self.part_id)}>"
|
|
|
|
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
class GroupExperiment(db.Model):
|
|
|
|
# An experiment specified to a group
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
part_experiment_id = db.Column(db.Integer, db.ForeignKey("part_experiment.id"), nullable=False)
|
|
|
|
group_id = db.Column(db.Integer, db.ForeignKey("group.id"), nullable=False)
|
|
|
|
appointments = db.relationship("Appointment", backref="group_experiment", lazy=True)
|
|
|
|
experiment_marks = db.relationship("ExperimentMark", backref="group_experiment", lazy=True)
|
|
|
|
|
|
|
|
|
|
|
|
class Experiment(db.Model):
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
2021-03-31 23:04:21 +00:00
|
|
|
number = db.Column(db.Integer, nullable=False, unique=True)
|
2021-03-18 13:53:55 +00:00
|
|
|
name = db.Column(db.String(200), nullable=False)
|
|
|
|
description = db.Column(db.Text, nullable=True)
|
|
|
|
room = db.Column(db.String(100), nullable=False)
|
|
|
|
building = db.Column(db.String(100), nullable=False)
|
|
|
|
responsibility = db.Column(db.String(200), nullable=True)
|
|
|
|
duration_in_days = db.Column(db.Integer, nullable=False)
|
2021-06-02 21:43:41 +00:00
|
|
|
deprecated = db.Column(db.Boolean, nullable=False, default=False) # To not be deleted!
|
2021-03-18 13:53:55 +00:00
|
|
|
oral_weighting = db.Column(db.Float, nullable=False)
|
|
|
|
protocol_weighting = db.Column(db.Float, nullable=False)
|
|
|
|
final_weighting = db.Column(db.Float, nullable=False)
|
|
|
|
part_experiments = db.relationship("PartExperiment", backref="experiment", lazy=True)
|
|
|
|
|
2021-04-24 10:05:58 +00:00
|
|
|
def __repr__(self):
|
2021-04-24 11:38:03 +00:00
|
|
|
return f"<Exp {self.number}>"
|
2021-04-24 10:05:58 +00:00
|
|
|
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
# Helper table for the many to many relationship between Assistant and PartExperiment
|
2021-06-02 21:43:41 +00:00
|
|
|
experiment_assistant = db.Table(
|
|
|
|
"experiment_assistant",
|
|
|
|
db.Column("part_experiment_id", db.Integer, db.ForeignKey("part_experiment.id"), primary_key=True),
|
|
|
|
db.Column("assistant_id", db.Integer, db.ForeignKey("assistant.id"), primary_key=True),
|
|
|
|
)
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
class PartExperiment(db.Model):
|
|
|
|
# An experiment in a specific part
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
experiment_id = db.Column(db.Integer, db.ForeignKey("experiment.id"), nullable=False)
|
|
|
|
part_id = db.Column(db.Integer, db.ForeignKey("part.id"), nullable=False)
|
2021-06-02 21:43:41 +00:00
|
|
|
assistants = db.relationship(
|
|
|
|
"Assistant", secondary=experiment_assistant, lazy=True, backref=db.backref("part_experiments", lazy=True)
|
|
|
|
)
|
2021-03-18 13:53:55 +00:00
|
|
|
group_experiments = db.relationship("GroupExperiment", backref="part_experiment", lazy=True)
|
|
|
|
|
|
|
|
|
|
|
|
class Assistant(db.Model):
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
first_name = db.Column(db.String(100), nullable=False)
|
|
|
|
last_name = db.Column(db.String(100), nullable=False)
|
|
|
|
email = db.Column(db.String(200), nullable=False)
|
|
|
|
phone_number = db.Column(db.String(50), nullable=True)
|
|
|
|
mobile_phone_number = db.Column(db.String(50), nullable=True)
|
|
|
|
room = db.Column(db.String(100), nullable=True)
|
|
|
|
building = db.Column(db.String(100), nullable=True)
|
|
|
|
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
|
|
|
|
appointments = db.relationship("Appointment", backref="assistant", lazy=True)
|
|
|
|
experiment_marks = db.relationship("ExperimentMark", backref="assistant", lazy=True)
|
|
|
|
|
2021-04-24 10:05:58 +00:00
|
|
|
def __repr__(self):
|
2021-04-24 11:38:03 +00:00
|
|
|
return f"<Assistant: {self.first_name} {self.last_name}>"
|
2021-04-24 10:05:58 +00:00
|
|
|
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
class Appointment(db.Model):
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
2021-06-02 21:43:41 +00:00
|
|
|
date = db.Column(db.DateTime, nullable=False) # To be specified with the python package "datetime"
|
|
|
|
special = db.Column(db.Boolean, nullable=False) # In the break or not
|
2021-03-18 13:53:55 +00:00
|
|
|
group_experiment_id = db.Column(db.Integer, db.ForeignKey("group_experiment.id"), nullable=False)
|
|
|
|
assistant_id = db.Column(db.Integer, db.ForeignKey("assistant.id"), nullable=False)
|
|
|
|
|
|
|
|
|
|
|
|
class Part(db.Model):
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
2021-06-02 21:43:41 +00:00
|
|
|
label = db.Column(db.String(100), nullable=False) # A/1, A/2, B/1, B/2
|
2021-03-18 13:53:55 +00:00
|
|
|
semester_id = db.Column(db.Integer, db.ForeignKey("semester.id"), nullable=False)
|
|
|
|
part_experiments = db.relationship("PartExperiment", backref="part", lazy=True)
|
|
|
|
part_students = db.relationship("PartStudent", backref="part", lazy=True)
|
2021-03-19 20:15:43 +00:00
|
|
|
groups = db.relationship("Group", backref="part", lazy=True)
|
2021-03-18 13:53:55 +00:00
|
|
|
|
2021-04-24 11:38:03 +00:00
|
|
|
def __repr__(self):
|
|
|
|
return f"<Part {self.label} {Semester.query.get(self.semester_id).label}>"
|
|
|
|
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
class Semester(db.Model):
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
2021-06-02 21:43:41 +00:00
|
|
|
label = db.Column(db.String(100), nullable=False, unique=True) # WS2122 for example
|
2021-03-18 13:53:55 +00:00
|
|
|
parts = db.relationship("Part", backref="semester", lazy=True)
|
|
|
|
|
2021-04-24 10:05:58 +00:00
|
|
|
def __repr__(self):
|
|
|
|
return f"<{self.label}>"
|
|
|
|
|
2021-06-01 23:56:49 +00:00
|
|
|
def createParts(self):
|
2021-06-08 23:07:02 +00:00
|
|
|
try:
|
|
|
|
for partLabel in getConfig("partLabels"):
|
|
|
|
db.session.add(Part(label=partLabel, semester=self))
|
|
|
|
db.session.commit()
|
|
|
|
except Exception as ex:
|
|
|
|
flash(ex, "error")
|
|
|
|
|
|
|
|
db.session.rollback()
|
2021-06-01 23:56:49 +00:00
|
|
|
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
class ExperimentMark(db.Model):
|
|
|
|
# A mark for a student after a specific experiment
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
oral_mark = db.Column(db.Integer, nullable=True)
|
|
|
|
protocol_mark = db.Column(db.Integer, nullable=True)
|
|
|
|
part_student_id = db.Column(db.Integer, db.ForeignKey("part_student.id"), nullable=False)
|
|
|
|
group_experiment_id = db.Column(db.Integer, db.ForeignKey("group_experiment.id"), nullable=False)
|
2021-06-02 21:43:41 +00:00
|
|
|
assistant_id = db.Column(
|
|
|
|
db.Integer, db.ForeignKey("assistant.id"), nullable=True
|
|
|
|
) # The assistant who gives the mark
|
2021-03-18 13:53:55 +00:00
|
|
|
|
|
|
|
|
2021-04-03 00:11:26 +00:00
|
|
|
class User(db.Model, FsUserMixin):
|
2021-03-18 13:53:55 +00:00
|
|
|
assistant = db.relationship("Assistant", backref="user", lazy=True, uselist=False)
|
2021-04-26 19:31:15 +00:00
|
|
|
active_semester_id = db.Column(db.Integer, nullable=True)
|
2021-04-03 00:11:26 +00:00
|
|
|
|
2021-04-24 10:05:58 +00:00
|
|
|
def __repr__(self):
|
2021-04-24 11:38:03 +00:00
|
|
|
return f"<User {self.email}>"
|
2021-04-24 10:05:58 +00:00
|
|
|
|
2021-04-03 00:11:26 +00:00
|
|
|
|
|
|
|
class Role(db.Model, FsRoleMixin):
|
2021-04-24 10:05:58 +00:00
|
|
|
def __repr__(self):
|
|
|
|
return f"<{self.name}>"
|