class Invitation(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    key_for_sharing = db.Column(db.String(40),
                                nullable=False,
                                unique=True,
                                default=lambda: str(uuid.uuid4()))

    inviter_id = db.Column(db.Integer,
                           db.ForeignKey('user.id'),
                           nullable=False)
    inviter = db.relationship('User', lazy='joined', backref='invites')

    team_id = db.Column(db.Integer, db.ForeignKey('team.id'), nullable=False)
    team = db.relationship('Team', lazy='joined', backref='invitations')

    invited_email = db.Column(db.String(127))
    message = db.Column(db.Text)
    status = db.Column(db.String(127))

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    @hybrid_property
    def is_deleted(self):
        return self.deleted_at == None

    @property
    def already_accepted(self):
        self.status == 'accepted'

    def mark_accepted(self):
        self.status = 'accepted'
class TeamUser(db.Model):
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    user = db.relationship('User', backref='team_users')

    team_id = db.Column(db.Integer, db.ForeignKey('team.id'), primary_key=True)
    team = db.relationship('Team', backref='team_users')

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    @hybrid_property
    def is_deleted(self):
        return self.deleted_at == None
class SurveyAnswer(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)

    mission_id = db.Column(db.Integer,
                           db.ForeignKey('mission.id'),
                           primary_key=True)
    mission = db.relationship('Mission',
                              backref='mission_survey_answers',
                              single_parent=True,
                              cascade='all, delete-orphan')

    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    user = db.relationship('User',
                           backref='user_survey_answers',
                           single_parent=True,
                           cascade='all, delete-orphan')

    question_id = db.Column(db.String(5))
    answer = db.Column(db.String(256))

    survey_version = db.Column(db.Integer)

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)
class MissionGoal(db.Model):
  mission_id = db.Column(db.Integer, db.ForeignKey('mission.id'), primary_key=True)
  mission = db.relationship('Mission', backref='mission_goals', single_parent=True, cascade='all, delete-orphan')

  goal_id = db.Column(db.Integer, db.ForeignKey('goal.id'), primary_key=True)
  goal = db.relationship('Goal', backref='goal_mission')

  week = db.Column(db.SmallInteger)

  created_at = db.Column(PendulumDateTimeField(), default=lambda: pendulum.now('UTC'))
  deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

  @hybrid_property
  def is_deleted(self):
    return self.deleted_at == None
class UserAchievement(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    name = db.Column(db.String(127))

    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    user = db.relationship('User', backref='achievements')

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    @hybrid_property
    def is_deleted(self):
        return self.deleted_at == None
Beispiel #6
0
class Goal(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    short_description = db.Column(db.Text)
    category = db.Column(db.String(127), default='diet')

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    visible_after = db.Column(PendulumDateTimeField(), nullable=True)
    hidden_after = db.Column(PendulumDateTimeField(), nullable=True)

    class Serializer(db.Model.Serializer):
        short_description = serpy.StrField()
        category = serpy.StrField()
        actual_goal = GoalSerializer()

    @property
    def actual_goal(self):
        cat_goals = GOALS_BY_CATEGORY[self.category]
        return [
            g for g in cat_goals['goals']
            if g['name'] == self.short_description
        ][0]

    @hybrid_property
    def is_visible(self):
        now = pendulum.now('UTC')
        return (((self.visible_after == None) | (self.visible_after < now)) &
                ((self.hidden_after == None) | (self.hidden_after > now)))

    @hybrid_property
    def is_deleted(self):
        return self.deleted_at == None
Beispiel #7
0
class Team(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(127), default='')
    description = db.Column(db.Text, default='Best. Crew. Ever.')

    captain_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    captain = db.relationship('User', backref='captain_of')

    members = association_proxy('team_users',
                                'user',
                                creator=lambda member: TeamUser(user=member))

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    def generic_invitation_from(self, inviter) -> Invitation:
        """returns an invitation not addressed to a particular email"""
        # find an existing invitation from this person
        for i in self.invitations:
            if i.inviter == inviter and i.invited_email is None:
                return i

        # if we got here, no such luck; gotta make our own luck
        invitation = Invitation(
            inviter=inviter,
            team=self,
        )
        invitation.save()

        return invitation

    @hybrid_property
    def is_deleted(self):
        return self.deleted_at == None
Beispiel #8
0
class Pledge(db.Model):
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)

    mission_id = db.Column(db.Integer,
                           db.ForeignKey('mission.id'),
                           primary_key=True)
    mission = db.relationship('Mission', backref='pledges')

    goal_id = db.Column(db.Integer, db.ForeignKey('goal.id'), primary_key=True)
    goal = db.relationship('Goal', backref='pledges')

    fulfilled = db.Column(db.Boolean, default=False)
    start_at = db.Column(PendulumDateTimeField, nullable=True, default=None)
    end_at = db.Column(PendulumDateTimeField, nullable=True, default=None)

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    @hybrid_property
    def is_deleted(self):
        return self.deleted_at == None
Beispiel #9
0
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(127), unique=True)
    name = db.Column(db.String(127), default='')
    password_hash = db.Column(db.String(127), nullable=True)

    email_confirmed = db.Column(db.Boolean, default=False)

    teams = association_proxy('team_users', 'team')

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    @hybrid_property
    def is_active(self):
        return self.deleted_at == None

    @property
    def first_name(self):
        return self.name.split(' ')[0]

    # required by Flask Login
    @property
    def is_authenticated(self):
        return True

    @property
    def is_anonymous(self):
        return False

    def get_id(self):
        return str(self.id)
Beispiel #10
0
class TeamAchievement(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    name = db.Column(db.String(127))

    team_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    team = db.relationship('Team', backref='achievements')

    mission_id = db.Column(db.Integer,
                           db.ForeignKey('mission.id'),
                           nullable=True)
    mission = db.relationship('Mission', backref='achievements')

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    @hybrid_property
    def is_deleted(self):
        return self.deleted_at == None
Beispiel #11
0
class Mission(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    uuid = db.Column(db.String(32),
                     unique=True,
                     default=lambda: uuid.uuid4().hex)

    title = db.Column(db.String(127), default='')
    short_description = db.Column(db.String(127), default='')
    duration_in_weeks = db.Column(db.SmallInteger, default=4)
    frozen = db.Column(db.Boolean, default=False)

    started_at = db.Column(PendulumDateTimeField(), nullable=True)

    team_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    team = db.relationship('Team', backref='missions')

    goals = association_proxy('mission_goals',
                              'goal',
                              creator=lambda goal: MissionGoal(goal=goal))

    created_at = db.Column(PendulumDateTimeField(),
                           default=lambda: pendulum.now('UTC'))
    deleted_at = db.Column(PendulumDateTimeField(), nullable=True)

    class Serializer(db.Model.Serializer):
        uuid = serpy.StrField()
        title = serpy.StrField()
        short_description = serpy.StrField()
        duration_in_weeks = serpy.IntField()

        goals = Goal.Serializer(many=True)

    @property
    def is_deleted(self):
        return self.deleted_at != None

    @property
    def days_until_start(self):
        time_left = self.start_time - pendulum.now('UTC')
        return time_left.in_days()

    @property
    def primary_goal_str(self):
        if not self.goals:
            return None
        else:
            return self.goals[0].short_description

    @property
    def co2_saved_str(self):
        # todo: pull from DB
        return '345kg'

    @property
    def start_time_str(self):
        return self.started_at.format('dddd [the] Do [of] MMMM')

    @property
    def end_time(self):
        return self.started_at.add(weeks=self.duration_in_weeks)

    @property
    def end_time_str(self):
        return self.end_time.format('dddd [the] Do [of] MMMM')

    @property
    def is_over(self):
        now = pendulum.now('UTC')
        mission_end_time = self.started_at.add(weeks=self.duration_in_weeks)
        return now >= mission_end_time

    @property
    def is_running(self):
        now = pendulum.now('UTC')
        mission_end_time = self.started_at.add(weeks=self.duration_in_weeks)
        return now < mission_end_time and now >= self.started_at and not self.is_deleted

    @property
    def is_upcoming(self):
        now = pendulum.now('UTC')
        return now < self.started_at and not self.is_deleted

    @property
    def start_time(self):
        return self.started_at

    @property
    def end_time(self):
        return self.started_at.add(weeks=self.duration_in_weeks)

    @property
    def mission_day(self):
        return (pendulum.now('UTC') - self.started_at).in_days()

    @property
    def duration_in_days(self):
        return self.duration_in_weeks * 7