eventcally/models.py
2020-07-30 11:31:37 +02:00

385 lines
16 KiB
Python

from app import db
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.orm import relationship, backref
from sqlalchemy.schema import CheckConstraint
from sqlalchemy.types import TypeDecorator
from sqlalchemy.event import listens_for
from sqlalchemy import UniqueConstraint, Boolean, DateTime, Column, Integer, String, ForeignKey, Unicode, UnicodeText, Numeric, LargeBinary
from flask_security import UserMixin, RoleMixin
from flask_dance.consumer.storage.sqla import OAuthConsumerMixin
from enum import IntEnum
import datetime
from db import IntegerEnum
### Base
class TrackableMixin(object):
created_at = Column(DateTime, default=datetime.datetime.utcnow)
@declared_attr
def created_by_id(cls):
return Column('created_by_id', ForeignKey('user.id'))
@declared_attr
def created_by(cls):
return relationship("User")
### Multi purpose
class Image(db.Model, TrackableMixin):
__tablename__ = 'image'
id = Column(Integer(), primary_key=True)
data = db.Column(db.LargeBinary)
encoding_format = Column(String(80))
### User
class RolesUsers(db.Model):
__tablename__ = 'roles_users'
id = Column(Integer(), primary_key=True)
user_id = Column('user_id', Integer(), ForeignKey('user.id'))
role_id = Column('role_id', Integer(), ForeignKey('role.id'))
class Role(db.Model, RoleMixin):
__tablename__ = 'role'
id = Column(Integer(), primary_key=True)
name = Column(String(80), unique=True)
description = Column(String(255))
permissions = Column(UnicodeText())
class User(db.Model, UserMixin):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
email = Column(String(255), unique=True)
username = Column(String(255))
password = Column(String(255))
last_login_at = Column(DateTime())
current_login_at = Column(DateTime())
last_login_ip = Column(String(100))
current_login_ip = Column(String(100))
login_count = Column(Integer)
active = Column(Boolean())
fs_uniquifier = Column(String(255))
confirmed_at = Column(DateTime())
roles = relationship('Role', secondary='roles_users',
backref=backref('users', lazy='dynamic'))
class OAuth(OAuthConsumerMixin, db.Model):
provider_user_id = Column(String(256), unique=True, nullable=False)
user_id = Column(Integer(), ForeignKey('user.id'), nullable=False)
user = db.relationship('User')
### Organization
class OrgMemberRolesMembers(db.Model):
__tablename__ = 'orgmemberroles_members'
id = Column(Integer(), primary_key=True)
member_id = Column('member_id', Integer(), ForeignKey('orgmember.id'))
role_id = Column('role_id', Integer(), ForeignKey('orgmemberrole.id'))
class OrgMemberRole(db.Model, RoleMixin):
__tablename__ = 'orgmemberrole'
id = Column(Integer(), primary_key=True)
name = Column(String(80), unique=True)
description = Column(String(255))
permissions = Column(UnicodeText())
class OrgMember(db.Model):
__tablename__ = 'orgmember'
id = Column(Integer(), primary_key=True)
organization_id = db.Column(db.Integer, db.ForeignKey('organization.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
user = db.relationship('User', backref=db.backref('orgmembers', lazy=True))
roles = relationship('OrgMemberRole', secondary='orgmemberroles_members',
backref=backref('members', lazy='dynamic'))
class Organization(db.Model, TrackableMixin):
__tablename__ = 'organization'
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), unique=True)
legal_name = Column(Unicode(255))
short_name = Column(Unicode(100), unique=True)
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location')
logo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
logo = db.relationship('Image', uselist=False)
url = Column(String(255))
email = Column(Unicode(255))
phone = Column(Unicode(255))
fax = Column(Unicode(255))
members = relationship('OrgMember', backref=backref('organization', lazy=True))
### Admin Unit
class AdminUnitMemberRolesMembers(db.Model):
__tablename__ = 'adminunitmemberroles_members'
id = Column(Integer(), primary_key=True)
member_id = Column('member_id', Integer(), ForeignKey('adminunitmember.id'))
role_id = Column('role_id', Integer(), ForeignKey('adminunitmemberrole.id'))
class AdminUnitMemberRole(db.Model, RoleMixin):
__tablename__ = 'adminunitmemberrole'
id = Column(Integer(), primary_key=True)
name = Column(String(80), unique=True)
description = Column(String(255))
permissions = Column(UnicodeText())
class AdminUnitMember(db.Model):
__tablename__ = 'adminunitmember'
id = Column(Integer(), primary_key=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
user = db.relationship('User', backref=db.backref('adminunitmembers', lazy=True))
roles = relationship('AdminUnitMemberRole', secondary='adminunitmemberroles_members',
backref=backref('members', lazy='dynamic'))
class AdminUnitOrgRoleOrganizations(db.Model):
__tablename__ = 'adminunitorgroles_organizations'
id = Column(Integer(), primary_key=True)
admin_unit_org_id = Column('admin_unit_org_id', Integer(), ForeignKey('adminunitorg.id'))
role_id = Column('role_id', Integer(), ForeignKey('adminunitorgrole.id'))
class AdminUnitOrgRole(db.Model, RoleMixin):
__tablename__ = 'adminunitorgrole'
id = Column(Integer(), primary_key=True)
name = Column(String(80), unique=True)
description = Column(String(255))
permissions = Column(UnicodeText())
class AdminUnitOrg(db.Model):
__tablename__ = 'adminunitorg'
id = Column(Integer(), primary_key=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
organization_id = db.Column(db.Integer, db.ForeignKey('organization.id'), nullable=False)
organization = db.relationship('Organization', backref=db.backref('adminunitorgs', lazy=True))
roles = relationship('AdminUnitOrgRole', secondary='adminunitorgroles_organizations',
backref=backref('organizations', lazy='dynamic'))
class AdminUnit(db.Model, TrackableMixin):
__tablename__ = 'adminunit'
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), unique=True)
short_name = Column(Unicode(100), unique=True)
members = relationship('AdminUnitMember', backref=backref('adminunit', lazy=True))
organizations = relationship('AdminUnitOrg', backref=backref('adminunit', lazy=True))
event_organizers = relationship('EventOrganizer', backref=backref('adminunit', lazy=True))
event_places = relationship('EventPlace', backref=backref('adminunit', lazy=True))
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location')
logo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
logo = db.relationship('Image', uselist=False)
url = Column(String(255))
email = Column(Unicode(255))
phone = Column(Unicode(255))
fax = Column(Unicode(255))
# Universal Types
class Actor(db.Model):
__tablename__ = 'actor'
__table_args__ = (UniqueConstraint('user_id', 'organization_id', 'admin_unit_id'),)
id = Column(Integer(), primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
user = db.relationship('User')
organization_id = db.Column(db.Integer, db.ForeignKey('organization.id'))
organization = db.relationship('Organization')
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'))
admin_unit = db.relationship('AdminUnit')
class OrgOrAdminUnit(db.Model):
__tablename__ = 'org_or_adminunit'
__table_args__ = (
CheckConstraint('NOT(organization_id IS NULL AND admin_unit_id IS NULL)'),
UniqueConstraint('organization_id', 'admin_unit_id'),
)
id = Column(Integer(), primary_key=True)
organization_id = db.Column(db.Integer, db.ForeignKey('organization.id'))
organization = db.relationship('Organization', lazy="joined", backref=backref('org_or_adminunit', cascade="all, delete-orphan", uselist=False, lazy=True))
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'))
admin_unit = db.relationship('AdminUnit', lazy="joined", backref=backref('org_or_adminunit', cascade="all, delete-orphan", uselist=False, lazy=True))
class Location(db.Model, TrackableMixin):
__tablename__ = 'location'
id = Column(Integer(), primary_key=True)
street = Column(Unicode(255))
postalCode = Column(Unicode(255))
city = Column(Unicode(255))
state = Column(Unicode(255))
country = Column(Unicode(255))
latitude = Column(Numeric(18,16))
longitude = Column(Numeric(19,16))
def is_empty(self):
return (not self.street
and not self.postalCode
and not self.city
and not self.state
and not self.country
and not self.latitude
and not self.longitude)
class Place(db.Model, TrackableMixin):
__tablename__ = 'place'
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), nullable=False)
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location', uselist=False)
photo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
photo = db.relationship('Image', uselist=False)
url = Column(String(255))
description = Column(UnicodeText())
def is_empty(self):
return (not self.name)
@listens_for(Place, 'before_insert')
@listens_for(Place, 'before_update')
def purge_place(mapper, connect, self):
if self.location and self.location.is_empty():
self.location_id = None
# Events
class EventPlace(db.Model, TrackableMixin):
__tablename__ = 'eventplace'
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), nullable=False)
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location', uselist=False)
photo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
photo = db.relationship('Image', uselist=False)
url = Column(String(255))
description = Column(UnicodeText())
public = Column(Boolean())
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=True)
organizer_id = db.Column(db.Integer, db.ForeignKey('eventorganizer.id'), nullable=True)
def is_empty(self):
return (not self.name)
@listens_for(EventPlace, 'before_insert')
@listens_for(EventPlace, 'before_update')
def purge_event_place(mapper, connect, self):
if self.location and self.location.is_empty():
self.location_id = None
class EventCategory(db.Model):
__tablename__ = 'eventcategory'
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), nullable=False, unique=True)
class EventSuggestion(db.Model, TrackableMixin):
__tablename__ = 'eventsuggestion'
id = Column(Integer(), primary_key=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
admin_unit = db.relationship('AdminUnit', backref=db.backref('eventsuggestions', lazy=True))
host_name = Column(Unicode(255), nullable=False)
event_name = Column(Unicode(255), nullable=False)
description = Column(UnicodeText(), nullable=False)
place_name = Column(Unicode(255), nullable=False)
place_street = Column(Unicode(255))
place_postalCode = Column(Unicode(255), nullable=False)
place_city = Column(Unicode(255), nullable=False)
contact_name = Column(Unicode(255), nullable=False)
contact_email = Column(Unicode(255), nullable=False)
external_link = Column(String(255))
dates = relationship('EventSuggestionDate', backref=backref('eventsuggestion', lazy=False), cascade="all, delete-orphan")
class EventSuggestionDate(db.Model):
__tablename__ = 'eventsuggestiondate'
id = Column(Integer(), primary_key=True)
event_suggestion_id = db.Column(db.Integer, db.ForeignKey('eventsuggestion.id'), nullable=False)
start = db.Column(db.DateTime(timezone=True), nullable=False)
#end: date_time
class EventTargetGroupOrigin(IntEnum):
both = 1
tourist = 2
resident = 3
class EventAttendanceMode(IntEnum):
offline = 1
online = 2
mixed = 3
class EventStatus(IntEnum):
scheduled = 1
cancelled = 2
movedOnline = 3
postponed = 4
rescheduled = 5
class EventOrganizer(db.Model, TrackableMixin):
__tablename__ = 'eventorganizer'
__table_args__ = (
CheckConstraint('NOT(name IS NULL AND org_name IS NULL)'),
)
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255))
org_name = Column(Unicode(255))
url = Column(String(255))
email = Column(Unicode(255))
phone = Column(Unicode(255))
fax = Column(Unicode(255))
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location')
logo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
logo = db.relationship('Image', uselist=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=True)
event_places = relationship('EventPlace', backref=backref('organizer', lazy=True))
def is_empty(self):
return (not self.name
and not self.org_name)
class Event(db.Model, TrackableMixin):
__tablename__ = 'event'
id = Column(Integer(), primary_key=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
admin_unit = db.relationship('AdminUnit', backref=db.backref('events', lazy=True))
organizer_id = db.Column(db.Integer, db.ForeignKey('eventorganizer.id'), nullable=True)
organizer = db.relationship('EventOrganizer', uselist=False)
host_id = db.Column(db.Integer, db.ForeignKey('org_or_adminunit.id'), nullable=True)
host = db.relationship('OrgOrAdminUnit', backref=db.backref('events', lazy=True))
place_id = db.Column(db.Integer, db.ForeignKey('place.id'), nullable=True)
place = db.relationship('Place', backref=db.backref('events', lazy=True))
event_place_id = db.Column(db.Integer, db.ForeignKey('eventplace.id'), nullable=True)
event_place = db.relationship('EventPlace', uselist=False)
name = Column(Unicode(255), nullable=False)
description = Column(UnicodeText(), nullable=False)
external_link = Column(String(255))
ticket_link = Column(String(255))
verified = Column(Boolean())
photo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
photo = db.relationship('Image', uselist=False)
category_id = db.Column(db.Integer, db.ForeignKey('eventcategory.id'), nullable=False)
category = relationship('EventCategory', uselist=False)
tags = Column(UnicodeText())
kid_friendly = Column(Boolean())
accessible_for_free = Column(Boolean())
age_from = Column(Integer())
age_to = Column(Integer())
target_group_origin = Column(IntegerEnum(EventTargetGroupOrigin))
attendance_mode = Column(IntegerEnum(EventAttendanceMode))
status = Column(IntegerEnum(EventStatus))
previous_start_date = db.Column(db.DateTime(timezone=True), nullable=True)
recurrence_rule = Column(UnicodeText())
start = db.Column(db.DateTime(timezone=True), nullable=True)
end = db.Column(db.DateTime(timezone=True), nullable=True)
dates = relationship('EventDate', backref=backref('event', lazy=False), cascade="all, delete-orphan")
@listens_for(Event, 'before_insert')
@listens_for(Event, 'before_update')
def purge_event(mapper, connect, self):
if self.organizer and self.organizer.is_empty():
self.organizer_id = None
if self.event_place and self.event_place.is_empty():
self.event_place_id = None
class EventDate(db.Model):
__tablename__ = 'eventdate'
id = Column(Integer(), primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False)
start = db.Column(db.DateTime(timezone=True), nullable=False)
end = db.Column(db.DateTime(timezone=True), nullable=True)