class FeedbackTagGroup(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) user = db.relationship("User", uselist=False) user_id = db.Column(db.Integer, db.ForeignKey("user.id")) tags = db.relationship( "FeedbackTag", order_by="asc(FeedbackTag.name)", lazy="dynamic", ) def __repr__(self): return f"<FeedbackTagGroup {self.name}>"
class Participants(SoftDeleteMixin, db.Model): user_id = db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True) pairing_session_id = db.Column( "pairing_session_id", db.Integer, db.ForeignKey("pairing_session.id"), primary_key=True, ) user = db.relationship("User") pairing_session = db.relationship("PairingSession")
class TaggedFeedback(db.Model): feedback_id = db.Column("feedback_id", db.Integer, db.ForeignKey("feedback.id"), primary_key=True) feedback_tag_id = db.Column( "feedback_tag_id", db.Integer, db.ForeignKey("feedback_tag.id"), primary_key=True, ) feedback = db.relationship("Feedback") tag = db.relationship("FeedbackTag")
class FeedbackTag(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), default='') description = db.Column(db.Text(), default='') group = db.relationship("FeedbackTagGroup", uselist=False) group_id = db.Column(db.Integer, db.ForeignKey("feedback_tag_group.id")) feedbacks = db.relationship( "Feedback", secondary="tagged_feedback", order_by="asc(Feedback.created_at)", lazy="dynamic", ) def __repr__(self): return f"<FeedbackTag {self.name}>"
class Team(db.Model): id = db.Column(db.Integer, primary_key=True) uuid = db.Column(UUID(as_uuid=True), default=uuid4, index=True) name = db.Column(db.String(64)) created_at = db.Column(db.DateTime, default=datetime.utcnow) all_users = db.relationship("User", backref="user", lazy="dynamic", order_by="asc(User.username)") all_reminders = db.relationship("Reminder", backref="reminder", lazy="dynamic") all_pairing_sessions = db.relationship("PairingSession", backref="pairing_session", lazy="dynamic") roles = db.relationship("Role", backref="role", lazy="dynamic") @hybrid_property def users(self): return self.all_users.filter(User.deleted == False) @users.setter def users(self, users): self.all_users = users @hybrid_property def pairing_sessions(self): return self.all_pairing_sessions.filter( PairingSession.deleted == False) @pairing_sessions.setter def pairing_sessions(self, pairing_sessions): self.all_pairing_sessions = pairing_sessions @hybrid_property def reminders(self): return self.all_reminders.filter(Reminder.deleted == False) @reminders.setter def reminders(self, reminders): self.all_reminders = reminders def __repr__(self): return f"<Team {self.name} {self.uuid} >"
class SoftDeleteMixin: deleted = db.Column(db.Boolean(), default=False) query_class = QueryWithSoftDelete def soft_delete(self): self.deleted = True db.session.commit() def revive(self): self.deleted = False db.session.commit()
class Role(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) color = db.Column(db.String(64), default="#7F9CF5") team = db.relationship("Team", uselist=False) team_id = db.Column(db.Integer, db.ForeignKey("team.id")) created_at = db.Column(db.DateTime, default=datetime.utcnow) all_users = db.relationship("User", lazy="dynamic", order_by="asc(User.username)") @hybrid_property def users(self): return self.all_users.filter(User.deleted == False) @users.setter def users(self, users): self.all_users = users def __repr__(self): return f"<Role {self.name} >"
class Reminder(SoftDeleteMixin, db.Model): id = db.Column(db.Integer, primary_key=True) user = db.relationship("User", uselist=False) user_id = db.Column(db.Integer, db.ForeignKey("user.id")) team = db.relationship("Team", uselist=False) team_id = db.Column(db.Integer, db.ForeignKey("team.id")) recuring_weekday = db.Column(db.Integer) message = db.Column(db.Text()) start_date = db.Column(db.DateTime) end_date = db.Column(db.DateTime) created_at = db.Column(db.DateTime, default=datetime.utcnow) def __repr__(self): return f"<Reminder {self.start_date} {self.end_date} {self.team.name}>"
class Feedback(db.Model): id = db.Column(db.Integer, primary_key=True) author_id = db.Column(db.Integer, db.ForeignKey("user.id")) author_name = db.Column(db.String(64)) recipient_id = db.Column(db.Integer, db.ForeignKey("user.id")) message = db.Column(db.Text()) created_at = db.Column(db.DateTime, default=datetime.utcnow) tags = db.relationship("FeedbackTag", secondary="tagged_feedback", passive_deletes=True, order_by="FeedbackTag.name") def __repr__(self): return f"<Feedback {self.id}>"
class PairingSession(SoftDeleteMixin, db.Model): FILTERED = {"UNPAIRED", "OUT_OF_OFFICE"} id = db.Column(db.Integer, primary_key=True) uuid = db.Column(UUID(as_uuid=True), default=uuid4, index=True) info = db.Column(db.Text, default="") created_at = db.Column(db.DateTime, default=datetime.utcnow) team = db.relationship("Team", uselist=False) team_id = db.Column(db.Integer, db.ForeignKey("team.id")) users = db.relationship("User", secondary="participants", passive_deletes=True, order_by="User.username") streak = db.Column(db.Integer, default=0) def __lt__(self, obj): return self.created_at.date() < obj.created_at.date() def __eq__(self, obj): return sorted(self.users) == sorted(obj.users)
class User(SoftDeleteMixin, db.Model): id = db.Column(db.Integer, primary_key=True) uuid = db.Column(UUID(as_uuid=True), default=uuid4, index=True) username = db.Column(db.String(64)) role = db.relationship("Role", uselist=False) role_id = db.Column(db.Integer, db.ForeignKey("role.id")) team = db.relationship("Team", uselist=False) team_id = db.Column(db.Integer, db.ForeignKey("team.id")) created_at = db.Column(db.DateTime, default=datetime.utcnow) reminders = db.relationship("Reminder", lazy="dynamic") feedback_tag_groups = db.relationship("FeedbackTagGroup", lazy="dynamic") feedback_authored = db.relationship('Feedback', foreign_keys='Feedback.author_id', backref='author', order_by="desc(Feedback.created_at)", lazy='dynamic') feedback_received = db.relationship('Feedback', foreign_keys='Feedback.recipient_id', backref='recipient', order_by="desc(Feedback.created_at)", lazy='dynamic') pairing_sessions = db.relationship( "PairingSession", secondary="participants", order_by="desc(PairingSession.created_at)", lazy="dynamic", ) email = db.Column(db.String(64), index=True, unique=True) password = db.Column(db.Text) full_name = db.Column(db.String(64)) ### start flask praetorian ### @classmethod def lookup(cls, email): return cls.query.filter_by(email=email).one_or_none() @classmethod def identify(cls, id): return cls.query.get(id) @property def identity(self): return self.id @property # not currently used but required by flask-praetorian def rolenames(self): return [] ### end flask praetorian ### def __lt__(self, obj): return self.username < obj.username def __repr__(self): return f"<User {self.username} {self.role and self.role.name or 'No Role'} >" @property def active_pairing_sessions(self): return self.pairing_sessions.filter( ~PairingSession.info.in_(PairingSession.FILTERED)).all() def csv_row(self): row = [] for pair in self.pairing_sessions.filter( ~PairingSession.info.in_(PairingSession.FILTERED)): members = ','.join( [user.username for user in pair.users if user is not self]) row.append( f"{self.username},{pair.created_at.strftime('%m/%d/%y')},{pair.info.replace(',', ' ')},{members}" ) return '\n'.join(row) def hard_delete(self): for pair in self.pairing_sessions: pair.users.remove(self) db.session.commit() self.role = None db.session.delete(self) db.session.commit() def soft_delete(self): for pair in self.pairing_sessions: if arrow.get(pair.created_at).to("US/Central") >= arrow.now( "US/Central").floor("days"): pair.users.remove(self) else: Participants.query.filter( Participants.pairing_session == pair).update( {Participants.deleted: True}) pair.soft_delete() self.reminders.update({Reminder.deleted: True}) super().soft_delete() def revive(self): for pair in self.pairing_sessions: Participants.query.with_deleted().filter( Participants.pairing_session == pair).update( {Participants.deleted: False}) pair.revive() todays_unpaired = (self.team.pairing_sessions.filter( PairingSession.created_at >= start_of_day(datetime.now())).filter( PairingSession.created_at < end_of_day(datetime.now())).filter( PairingSession.info == 'UNPAIRED').first()) todays_unpaired.users.append(self) self.reminders.update({Reminder.deleted: False}) super().revive()