class User(db.Model): __tablename__ = "users" __table_args__ = (db.UniqueConstraint('email', 'tenant_id'), ) id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(60), nullable=False) name = db.Column(db.String(30), nullable=False) _password = db.Column("password", db.String(), nullable=False) is_admin = db.Column(db.Boolean(), nullable=False) is_owner = db.Column(db.Boolean(), nullable=False, default=False) created_at = db.Column(db.DateTime(timezone=False), nullable=False, server_default=now()) expires_on = db.Column(db.DateTime(), nullable=False, default=get_expiry) tenant_id = db.Column(db.Integer, db.ForeignKey('tenants.id', ondelete="CASCADE"), nullable=False) @hybrid_property def password(self): return self._password @password.setter def password(self, password): self._password = bcrypt.generate_password_hash(password).decode( 'utf-8') def __repr__(self): return f"email:{self.email} -- id:{self.id} -- tenant_id:{self.tenant_id}"
class Song(db.Model): __table_args__ = ( db.UniqueConstraint('order', 'spotify_id', 'playlist_id'), ) id = db.Column(db.Integer, primary_key=True) order = db.Column(db.Integer, nullable=False) spotify_id = db.Column(db.String(22), nullable=False) name = db.Column(db.String(100), nullable=False) album = db.Column(db.String(100), nullable=False) artist = db.Column(db.String(100), nullable=False) popularity = db.Column(db.Integer, nullable=False) posts = db.relationship('Post', backref='song', lazy=True) playlist_id = db.Column(db.Integer, db.ForeignKey('playlist.id'), nullable=False) danceability = db.Column(db.Float) energy = db.Column(db.Float) key = db.Column(db.Integer) mode = db.Column(db.Integer) speechiness = db.Column(db.Float) acousticness = db.Column(db.Float) instrumentalness = db.Column(db.Float) liveness = db.Column(db.Float) valence = db.Column(db.Float) tempo = db.Column(db.Float) uri = db.Column(db.String(36)) time_signature = db.Column(db.Integer) def __repr__(self): return f"Song('{self.name}', '{self.album}')"
class ABExperiment(db.Model): __tablename__ = "experiment" # unique constraint on multiple fields: __table_args__ = (db.UniqueConstraint('app_id', 'name', name="unique_constraint_app_exp"), ) id = db.Column(db.Integer, primary_key=True) app_id = db.Column(db.Integer, db.ForeignKey("app.id")) name = db.Column(db.String(120), index=True) description = db.Column(db.Text) metrics = db.Column(db.Text) start_date = db.Column(db.Date) end_date = db.Column(db.Date) options = db.relationship('ABOption', backref='experiment') # cascade="all, delete-orphan" @property def metrics_json(self): return json.loads(self.metrics) if self.metrics is not None else dict() @property def clean_name(self): clean_name = " ".join( [i.capitalize() for i in self.name.split("_") if i not in ("exp", "ios", "android")] ) return clean_name @property def sorted_options(self): options = sorted(self.options, key=lambda x: (-x.is_control_group, x.name)) return [i.name for i in options] def is_period_data_exists(self, period): """ Chech, wether data exists for requested period (cnt_users > 0 for all options) """ return all([i > 0 for i in self.metrics_json.get(f"cnt_users_{period}").values()]) def get_user_donut_svg_url(self): return f'img/ab/{self.name}/user_donut.svg' def get_user_dynamics_svg_url(self): return f'img/ab/{self.name}/user_dynamics.svg' def get_pdf_and_confint_svg_url(self, col_name="conversion", period="all"): return f'img/ab/{self.name}/pdf_{col_name}_{period}.svg' def get_valueset_total(self, col_name='cnt_users'): """ Format for further barplot_total, being rendered with chart.js """ if not self.metrics_json: return valueset = {i: [] for i in self.sorted_options} for period in ["1d", "7d", "30d", "all"]: tmp = self.metrics_json[f"{col_name}_{period}"] for option in valueset.keys(): valueset[option].append(tmp[option]) return valueset def __repr__(self): return f'<Exp: {self.name}>'
class FoodCategory(db.Model): __tablename__ = 'foodcategory' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(128), nullable=False) db.UniqueConstraint(name) def __init__(self, name): self.name = name def to_json(self): return {'id': self.id, 'name': self.name}
class Location(db.Model): __tablename__ = 'location' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(128), nullable=False) gpid = db.Column(db.String(128), nullable=True) types = db.Column(db.String(128), nullable=True) db.UniqueConstraint(name, gpid) def __init__(self, name, gpid, types): self.name = name self.gpid = gpid self.types = types
class Tag(SpecialBase): __tablename__ = "tag" parent_id = db.Column(db.Integer, db.ForeignKey('tag.id'), nullable=True, unique=False) children = db.relationship('Tag', lazy=True) def __repr__(self): return f"Tag('{self.name}')" db.UniqueConstraint('name', name='tag_uq')
class Playlist(db.Model): __table_args__ = ( db.UniqueConstraint('user_id', 'spotify_id'), ) id = db.Column(db.Integer, primary_key=True) spotify_id = db.Column(db.String(22), nullable=False) title = db.Column(db.String(100), nullable=False) genre = db.Column(db.String(25)) date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) user_id = db.Column(db.String(30), db.ForeignKey('user.id'), nullable=False) posts = db.relationship('Post', backref='topic', lazy=True) songs = db.relationship('Song', backref='topic', lazy=True) def __repr__(self): return f"('id',{self.id}),('title',{self.title}), ('date',{self.date_posted})"
class FoodType(db.Model): __tablename__ = 'foodtype' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(128), nullable=False) catid = db.Column(db.Integer, db.ForeignKey('foodcategory.id')) isvisible = db.Column(db.Boolean(), default=False, nullable=False) db.UniqueConstraint(name, catid) def __init__(self, name, catid, isvisible): self.name = name self.catid = catid self.isvisible = isvisible def to_json(self): return { 'id': self.id, 'name': self.name, 'category_id': self.catid, 'category_name': FoodCategory.query.filter_by(id=self.catid).first().name }