class Event(BaseScopedNameMixin, db.Model): __tablename__ = 'event' profile_id = db.Column(db.Integer, db.ForeignKey('profile.id'), nullable=False) profile = db.relationship(Profile) parent = db.synonym('profile') venue_id = db.Column(db.Integer, db.ForeignKey('venue.id'), nullable=False) venue = db.relationship('Venue') blurb = db.Column(db.Unicode(250), default=u'', nullable=False) description = db.Column(db.UnicodeText, default=u'', nullable=False) start_datetime = db.Column(db.DateTime, nullable=False) end_datetime = db.Column(db.DateTime, nullable=False) maximum_participants = db.Column(db.Integer, default=0, nullable=False) website = db.Column(db.Unicode(250), default=u'', nullable=False) status = db.Column(db.Integer, nullable=False, default=EVENT_STATUS.DRAFT) ticket_price = db.Column(db.Unicode(250), nullable=False, default=u'') __table_args__ = (db.UniqueConstraint('name', 'profile_id'), ) def owner_is(self, user): """Check if a user is an owner of this event""" return user is not None and self.profile.userid in user.user_organizations_owned_ids( ) def participant_is(self, user): from hacknight.models.participant import Participant return Participant.get(user, self) is not None def confirmed_participant_is(self, user): from hacknight.models.participant import Participant, PARTICIPANT_STATUS p = Participant.get(user, self) return p and p.status == PARTICIPANT_STATUS.CONFIRMED
class Participant(BaseMixin, db.Model): __tablename__ = 'participant' user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship(User) event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) event = db.relationship(Event, backref=db.backref('participants', cascade='all, delete-orphan')) status = db.Column(db.Integer, default=PARTICIPANT_STATUS.PENDING, nullable=False) mentor = db.Column(db.Boolean, default=False, nullable=False) reason_to_join = db.Column(db.UnicodeText, default=u'', nullable=False) email = db.Column(db.Unicode(80), default=u'', nullable=False) phone_no = db.Column(db.Unicode(15), default=u'', nullable=False) job_title = db.Column(db.Unicode(120), default=u'', nullable=False) company = db.Column(db.Unicode(1200), default=u'', nullable=False) def save_defaults(self): user = self.user user.phone_no = self.phone_no user.job_title = self.job_title user.company = self.company @classmethod def get(cls, user, event): return cls.query.filter_by(user=user).filter_by(event=event).first()
class Sponsor(BaseScopedNameMixin, db.Model): __tablename__ = 'sponsor' event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) event = db.relation(Event, backref=db.backref('sponsors', cascade='all, delete-orphan')) parent = db.synonym('event') website = db.Column(db.Unicode(250), nullable=True) image_url = db.Column(db.Unicode(250), nullable=False) description = db.Column(db.UnicodeText, nullable=False) __table_args__ = (db.UniqueConstraint('name', 'event_id'), )
class Participant(BaseMixin, db.Model): __tablename__ = 'participant' user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship(User) event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) event = db.relationship(Event, backref=db.backref('participants', cascade='all, delete-orphan')) status = db.Column(db.Integer, default=PARTICIPANT_STATUS.PENDING, nullable=False) mentor = db.Column(db.Boolean, default=False, nullable=False) reason_to_join = db.Column(db.UnicodeText, default=u'', nullable=False) email = db.Column(db.Unicode(80), default=u'', nullable=False) phone_no = db.Column(db.Unicode(15), default=u'', nullable=False) job_title = db.Column(db.Unicode(120), default=u'', nullable=False) company = db.Column(db.Unicode(1200), default=u'', nullable=False) skill_level = db.Column(db.Unicode(120), default=u'', nullable=False) NON_CONFIRMED_STATUSES = (PARTICIPANT_STATUS.PENDING, PARTICIPANT_STATUS.WL) @classmethod def unconfirmed_for(cls, event): return cls.query.filter( cls.status.in_([PARTICIPANT_STATUS.PENDING, PARTICIPANT_STATUS.WL]), cls.event == event).all() def save_defaults(self): user = self.user user.phone_no = self.phone_no user.job_title = self.job_title user.company = self.company def confirm(self): self.status = PARTICIPANT_STATUS.CONFIRMED @classmethod def get(cls, user, event): return cls.query.filter_by(user=user).filter_by(event=event).first() @property def is_participating(self): return self.status in (PARTICIPANT_STATUS.CONFIRMED, PARTICIPANT_STATUS.ATTENDED)
class User(UserBase, db.Model): __tablename__ = 'user' email = db.Column(db.Unicode(80), default=u'', nullable=True) phone_no = db.Column(db.Unicode(15), default=u'', nullable=True) job_title = db.Column(db.Unicode(120), default=u'', nullable=True) company = db.Column(db.Unicode(1200), default=u'', nullable=True) @property def profile_url(self): return url_for('profile_view', profile=self.username or self.userid) @property def profile(self): return Profile.query.filter_by(userid=self.userid).first() @property def profiles(self): return [self.profile] + Profile.query.filter( Profile.userid.in_(self.organizations_owned_ids())).order_by('title').all()
class Profile(BaseNameMixin, db.Model): __tablename__ = 'profile' userid = db.Column(db.Unicode(22), nullable=False, unique=True) description = db.Column(db.UnicodeText, default=u'', nullable=False) type = db.Column(db.Integer, default=PROFILE_TYPE.UNDEFINED, nullable=False) def type_label(self): return profile_types.get(self.type, profile_types[0])
class Sponsor(BaseScopedNameMixin, db.Model): __tablename__ = 'sponsor' event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) event = db.relation(Event, backref=db.backref('sponsors', cascade='all, delete-orphan')) parent = db.synonym('event') website = db.Column(db.Unicode(250), nullable=True) image_url = db.Column(db.Unicode(250), nullable=False) description = db.Column(db.UnicodeText, nullable=False) __table_args__ = (db.UniqueConstraint('name', 'event_id'), ) def url_for(self, action='view', _external=False): if action == 'view': return url_for('sponsor_view', profile=self.event.profile.name, event=self.event.name, sponsor=self.name)
class EventRedirect(BaseMixin, db.Model): __tablename__ = "event_redirect" profile_id = db.Column(db.Integer, db.ForeignKey('profile.id'), nullable=False) profile = db.relationship(Profile) name = db.Column(db.Unicode(250), nullable=False) event_id = db.Column(None, db.ForeignKey('event.id'), nullable=False) event = db.relationship(Event, backref=db.backref('redirects', cascade='all, delete-orphan')) __table_args__ = (db.UniqueConstraint(profile_id, name), )
class ProjectMember(BaseMixin, db.Model): __tablename__ = 'project_member' project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) # project = db.relationship(Project, backref=db.backref('members', cascade='all, delete-orphan')) participant_id = db.Column(db.Integer, db.ForeignKey('participant.id'), nullable=False) participant = db.relationship( Participant, backref=db.backref('projects', cascade='all, delete-orphan')) status = db.Column(db.Integer, nullable=False, default=0) role = db.Column(db.Unicode(250), nullable=False, default=u'') __table_args__ = (db.UniqueConstraint('project_id', 'participant_id'), )
class Profile(ProfileMixin, BaseNameMixin, db.Model): __tablename__ = 'profile' userid = db.Column(db.Unicode(22), nullable=False, unique=True) description = db.Column(db.UnicodeText, default=u'', nullable=False) type = db.Column(db.Integer, default=PROFILE_TYPE.UNDEFINED, nullable=False) def type_label(self): return profile_types.get(self.type, profile_types[0]) def url_for(self, action='view', _external=True): if action == 'view': return url_for('profile_view', profile=self.name, _external=_external) elif action == 'new-event': return url_for('event_new', profile=self.name, _external=_external)
class Venue(BaseNameMixin, db.Model): __tablename__ = 'venue' profile_id = db.Column(db.Integer, db.ForeignKey('profile.id'), nullable=False) profile = db.relationship(Profile) description = db.Column(db.UnicodeText, default=u'', nullable=False) address1 = db.Column(db.Unicode(80), default=u'', nullable=False) address2 = db.Column(db.Unicode(80), default=u'', nullable=False) city = db.Column(db.Unicode(30), default=u'', nullable=False) state = db.Column(db.Unicode(30), default=u'', nullable=False) postcode = db.Column(db.Unicode(20), default=u'', nullable=False) country = db.Column(db.Unicode(2), default=u'', nullable=False) latitude = db.Column(db.Numeric(8, 5), nullable=True) longitude = db.Column(db.Numeric(8, 5), nullable=True) timezone = db.Column(db.Unicode(40), nullable=False) def url_for(self, action='view', _external=False): if action == 'view': return url_for('venue_view', venue=self.name, _external=_external)
class Venue(BaseNameMixin, db.Model): __tablename__ = 'venue' profile_id = db.Column(db.Integer, db.ForeignKey('profile.id'), nullable=False) profile = db.relationship(Profile) description = db.Column(db.UnicodeText, default=u'', nullable=False) address1 = db.Column(db.Unicode(80), default=u'', nullable=False) address2 = db.Column(db.Unicode(80), default=u'', nullable=False) city = db.Column(db.Unicode(30), default=u'', nullable=False) state = db.Column(db.Unicode(30), default=u'', nullable=False) postcode = db.Column(db.Unicode(20), default=u'', nullable=False) country = db.Column(db.Unicode(2), default=u'', nullable=False) latitude = db.Column(db.Numeric(7, 4), nullable=True) longitude = db.Column(db.Numeric(7, 4), nullable=True)
class ProjectMember(BaseMixin, db.Model): __tablename__ = 'project_member' project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) #: User who created this project user_id = db.Column(None, db.ForeignKey('user.id'), nullable=False) user = db.relationship(User, backref=db.backref('project_memberships', cascade='all, delete-orphan')) status = db.Column(db.Integer, nullable=False, default=0) role = db.Column(db.Unicode(250), nullable=False, default=u'') __table_args__ = (db.UniqueConstraint('project_id', 'user_id'), ) def permissions(self, user, inherited=None): perms = super(ProjectMember, self).permissions(user, inherited) if user is not None and user == self.project.user and self.user != user: perms.add('remove-member') return perms
class Project(BaseScopedIdNameMixin, db.Model): __tablename__ = 'project' event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) event = db.relation(Event, backref=db.backref('projects', order_by=db.desc('url_id'), cascade='all, delete-orphan')) parent = db.synonym('event') #: User who is part of this project user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship(User, backref='projects') blurb = db.Column(db.Unicode(250), nullable=False) description = db.Column(db.UnicodeText, nullable=False) maximum_size = db.Column(db.Integer, default=0, nullable=False) #: Is the project owner participating? participating = db.Column(db.Boolean, nullable=False, default=True) members = db.relationship('ProjectMember', backref='project', uselist=True) votes_id = db.Column(db.Integer, db.ForeignKey('votespace.id'), nullable=False) votes = db.relationship(VoteSpace, uselist=False) comments_id = db.Column(db.Integer, db.ForeignKey('commentspace.id'), nullable=False) comments = db.relationship(CommentSpace, uselist=False) __table_args__ = (db.UniqueConstraint('url_id', 'event_id'), ) def __init__(self, **kwargs): super(Project, self).__init__(**kwargs) if not self.votes: self.votes = VoteSpace(type=0) if not self.comments: self.comments = CommentSpace() @property def users(self): return set([self.user] + [m.user for m in self.members]) participants = users def owner_is(self, user): return user is not None and self.user == user def getnext(self): return Project.query.filter(Project.event == self.event).filter( Project.id != self.id).filter( Project.created_at < self.created_at).order_by( db.desc('created_at')).first() def getprev(self): return Project.query.filter(Project.event == self.event).filter( Project.id != self.id).filter(Project.created_at > self.created_at ).order_by('created_at').first() def url_for(self, action='view', _external=False): if action == 'view': return url_for('project_view', profile=self.event.profile.name, event=self.event.name, project=self.url_name, _external=_external) elif action == 'edit': return url_for('project_edit', profile=self.event.profile.name, event=self.event.name, project=self.url_name, _external=_external) elif action == 'delete': return url_for('project_delete', profile=self.event.profile.name, event=self.event.name, project=self.url_name, _external=_external) elif action == 'voteup': return url_for('project_voteup', profile=self.event.profile.name, event=self.event.name, project=self.url_name, _external=_external) elif action == 'votedown': return url_for('project_votedown', profile=self.event.profile.name, event=self.event.name, project=self.url_name, _external=_external) elif action == 'cancelvote': return url_for('project_cancelvote', profile=self.event.profile.name, event=self.event.name, project=self.url_name, _external=_external) elif action == 'prev': return url_for('project_view', profile=self.event.profile.name, event=self.event.name, project=self.getprev().url_name, _external=_external) elif action == 'next': return url_for('project_view', profile=self.event.profile.name, event=self.event.name, project=self.getnext().url_name, _external=_external) elif action == 'join': return url_for('project_join', profile=self.event.profile.name, event=self.event.name, project=self.url_name, _external=_external)
class Project(BaseScopedIdNameMixin, db.Model): __tablename__ = 'project' event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False) event = db.relation(Event, backref=db.backref('projects', cascade='all, delete-orphan')) parent = db.synonym('event') #: Participant who created this project participant_id = db.Column(None, db.ForeignKey('participant.id'), nullable=False) participant = db.relationship(Participant) blurb = db.Column(db.Unicode(250), nullable=False) description = db.Column(db.UnicodeText, nullable=False) maximum_size = db.Column(db.Integer, default=0, nullable=False) #: Is the project owner participating? participating = db.Column(db.Boolean, nullable=False, default=True) members = db.relationship('ProjectMember', backref='project', lazy='dynamic') votes_id = db.Column(db.Integer, db.ForeignKey('votespace.id'), nullable=False) votes = db.relationship(VoteSpace, uselist=False) comments_id = db.Column(db.Integer, db.ForeignKey('commentspace.id'), nullable=False) comments = db.relationship(CommentSpace, uselist=False) __table_args__ = (db.UniqueConstraint('url_id', 'event_id'), ) def __init__(self, **kwargs): super(Project, self).__init__(**kwargs) if not self.votes: self.votes = VoteSpace(type=0) if not self.comments: self.comments = CommentSpace() @property def user(self): return self.participant.user @property def participants(self): return set([self.participant] + [m.participant for m in self.members]) @property def users(self): return set([self.user] + [m.participant.user for m in self.members]) def owner_is(self, user): return self.user == user def getnext(self): return Project.query.filter(Project.event == self.event).filter( Project.id != self.id).filter( Project.created_at < self.created_at).order_by( db.desc('created_at')).first() def getprev(self): return Project.query.filter(Project.event == self.event).filter( Project.id != self.id).filter(Project.created_at > self.created_at ).order_by('created_at').first()
class Event(BaseScopedNameMixin, db.Model): __tablename__ = 'event' profile_id = db.Column(db.Integer, db.ForeignKey('profile.id'), nullable=False) profile = db.relationship(Profile) parent = db.synonym('profile') venue_id = db.Column(db.Integer, db.ForeignKey('venue.id'), nullable=False) venue = db.relationship('Venue') blurb = db.Column(db.Unicode(250), default=u'', nullable=False) description = db.Column(db.UnicodeText, default=u'', nullable=False) apply_instructions = db.Column(db.UnicodeText, default=u'', nullable=False) start_datetime = db.Column(db.DateTime, nullable=False) end_datetime = db.Column(db.DateTime, nullable=False) maximum_participants = db.Column(db.Integer, default=0, nullable=False) website = db.Column(db.Unicode(250), default=u'', nullable=False) status = db.Column(db.Integer, nullable=False, default=EVENT_STATUS.DRAFT) ticket_price = db.Column(db.Unicode(250), nullable=False, default=u'') confirmation_message = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) confirmation_message_text = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) waitlisted_message = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) waitlisted_message_text = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) rejected_message = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) rejected_message_text = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) pending_message = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) pending_message_text = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) __table_args__ = (db.UniqueConstraint('name', 'profile_id'), ) def owner_is(self, user): """Check if a user is an owner of this event""" return user is not None and self.profile.userid in user.user_organizations_owned_ids( ) def participant_is(self, user): from hacknight.models.participant import Participant return Participant.get(user, self) is not None def confirmed_participant_is(self, user): from hacknight.models.participant import Participant, PARTICIPANT_STATUS p = Participant.get(user, self) return p and p.status == PARTICIPANT_STATUS.CONFIRMED def permissions(self, user, inherited=None): perms = super(Event, self).permissions(user, inherited) if user is not None and user.userid == self.profile.userid or self.status in [ EVENT_STATUS.PUBLISHED, EVENT_STATUS.ACTIVE, EVENT_STATUS.COMPLETED, EVENT_STATUS.CANCELLED, EVENT_STATUS.CLOSED ]: perms.add('view') if user is not None and self.profile.userid in user.user_organizations_owned_ids( ): perms.add('edit') perms.add('delete') perms.add('send-email') return perms def url_for(self, action='view', _external=False): if action == 'view': return url_for('event_view', profile=self.profile.name, event=self.name, _external=_external) elif action == 'edit': return url_for('event_edit', profile=self.profile.name, event=self.name, _external=_external) elif action == 'delete': return url_for('event_delete', profile=self.profile.name, event=self.name, _external=_external) elif action == 'new-project': return url_for('project_new', profile=self.profile.name, event=self.name, _external=_external) elif action == 'apply': return url_for('event_apply', profile=self.profile.name, event=self.name, _external=_external) elif action == 'withdraw': return url_for('event_withdraw', profile=self.profile.name, event=self.name, _external=_external) elif action == 'open': return url_for('event_open', profile=self.profile.name, event=self.name, _external=_external) elif action == 'export': return url_for('event_export', profile=self.profile.name, event=self.name, _external=_external) elif action == 'send_email': return url_for('event_send_email', profile=self.profile.name, event=self.name, _external=_external) elif action == 'email_template': return url_for('email_template_form', profile=self.profile.name, event=self.name, _external=_external)
class Event(BaseScopedNameMixin, db.Model): __tablename__ = 'event' profile_id = db.Column(db.Integer, db.ForeignKey('profile.id'), nullable=False) profile = db.relationship(Profile) parent = db.synonym('profile') venue_id = db.Column(db.Integer, db.ForeignKey('venue.id'), nullable=True) venue = db.relationship('Venue') blurb = db.Column(db.Unicode(250), default=u'', nullable=False) description = db.Column(db.UnicodeText, default=u'', nullable=False) apply_instructions = db.Column(db.UnicodeText, default=u'', nullable=False) start_datetime = db.Column(db.DateTime, nullable=False) end_datetime = db.Column(db.DateTime, nullable=False) maximum_participants = db.Column(db.Integer, default=0, nullable=False) website = db.Column(db.Unicode(250), default=u'', nullable=False) status = db.Column(db.Integer, nullable=False, default=EVENT_STATUS.DRAFT) ticket_price = db.Column(db.Unicode(250), nullable=False, default=u'') confirmation_message = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) confirmation_message_text = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) waitlisted_message = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) waitlisted_message_text = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) rejected_message = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) rejected_message_text = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) pending_message = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) pending_message_text = deferred( db.Column(db.UnicodeText, nullable=False, default=u'')) # Sync details sync_service = db.Column(db.Unicode(100), nullable=True) sync_credentials = db.Column(db.Unicode(100), nullable=True) sync_eventsid = db.Column(db.Unicode(100), nullable=True) __table_args__ = (db.UniqueConstraint('name', 'profile_id'), ) # List of statuses which are not allowed to be displayed in index page. NON_DISPLAYABLE_STATUSES = (EVENT_STATUS.DRAFT, EVENT_STATUS.CANCELLED, EVENT_STATUS.UNLISTED) @classmethod def upcoming_events(cls): return cls.query.filter( cls.end_datetime > datetime.utcnow(), not_(cls.status.in_(cls.NON_DISPLAYABLE_STATUSES))).order_by( cls.start_datetime.asc()).all() @classmethod def past_events(cls): return cls.query.filter( cls.end_datetime < datetime.utcnow(), not_(cls.status.in_(cls.NON_DISPLAYABLE_STATUSES))).order_by( cls.end_datetime.desc()).all() def owner_is(self, user): """Check if a user is an owner of this event""" return user is not None and self.profile.userid in user.user_organizations_owned_ids( ) def has_sync(self): return self.sync_service and self.sync_credentials and self.sync_eventsid def _fetch_and_sync(self, event_id, participants): """Fetch data from external service like doattend""" from hacknight import lastuser if self.sync_service == SYNC_SERVICE.DOATTEND: data_url = u"http://doattend.com/api/events/{event_id}/participants_list.json?api_key={credentials}".format( event_id=event_id, credentials=self.sync_credentials) try: r = requests.get(data_url) except requests.ConnectionError: raise SyncException(u"Unable to connect to internet") if r.status_code == 200: registered_participants = r.json() if callable( r.json) else r.json emails = set([ p.get('Email') for p in registered_participants['participants'] ]) for participant in participants: if participant.email in emails or emails.intersection( set(lastuser.user_emails(participant.user))): participant.confirm() yield u"{email} is confirmed.\n".format( email=participant.email) yield u"Synced all participants.\n" else: raise SyncException( u"Sync service failed with status code {code}".format( code=r.status_code)) def sync_participants(self, participants): final_msg = u"<a href=\"{url}\">Click here for hacknight page.</a>\n".format( url=self.url_for()) if self.has_sync(): for event_id in self.sync_eventsid.split(','): try: for msg in self._fetch_and_sync(event_id.strip(), participants): yield msg except SyncException, e: yield unicode(e) db.session.commit() yield Markup(final_msg) else: