class Profile(db.Model): __tablename__ = 'profile' id = db.Column(db.Integer, primary_key=True) tag = db.Column(db.String(50), unique=True) platform = db.Column(db.Enum(PlatformEnum)) region = db.Column(db.Enum(RegionEnum)) stats = db.relationship('Stat', backref='profile', cascade='all, delete-orphan', lazy='dynamic') def __init__(self, tag=None, ): self.name = name self.description = description def __repr__(self): return '<Profile %r>' % (self.tag)
class Attestation(db.Model): id = db.Column(db.Integer, primary_key=True) method = db.Column(db.Enum(AttestationTypes)) eth_address = db.Column(db.String) value = db.Column(db.String) signature = db.Column(db.String) created_at = db.Column(db.DateTime, default=datetime.utcnow)
class Engagement(BaseModel): """Engagement model. Args: BaseModel: Base model. """ __tablename__ = 'engagement' title = db.Column(db.String(256)) description = db.Column(db.String(256)) start_date = db.Column(db.Date) end_date = db.Column(db.Date) color = db.Column(db.String(7)) status = db.Column( db.Enum(EngagementStatus), default=EngagementStatus.NOT_STARTED) manager_id = db.Column(UUID, nullable=True) partner_id = db.Column(UUID, nullable=True) client_id = db.Column(UUID, db.ForeignKey('client.id')) client = relationship('Client') line_of_service_id = db.Column( UUID, db.ForeignKey('line_of_service.id')) line_of_service = relationship('LineOfService') organization_id = db.Column(UUID, db.ForeignKey('organization.id')) organization = relationship('Organization') def __repr__(self): return '<Engagement %s>' % self.title
class DonationModel(db.Model): __tablename__ = "donations" id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) attendance_id = db.Column(db.Integer, db.ForeignKey("attendances.id"), nullable=False) transfer_id = db.Column(db.Integer, db.ForeignKey("transfers.id"), nullable=True) year = db.Column(db.Integer, nullable=False) month = db.Column( db.Enum("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december", name="month")) mmk_amount = db.Column(db.Float()) jpy_amount = db.Column(db.Float()) paid_at = db.Column(db.DateTime(), nullable=True) def __init__(self, user_id: int, attendance_id: int, transfer_id: int, year: int, month: str, mmk_amount: float, jpy_amount: float, paid_at: datetime) -> None: self.user_id = user_id self.attendance_id = attendance_id self.transfer_id = transfer_id self.year = year self.month = month self.mmk_amount = mmk_amount self.jpy_amount = jpy_amount self.paid_at = paid_at def __repr__(self): return f"<Donation Records for user_id {self.user_id}>" @staticmethod def create_donation(new_donation) -> bool: """ create new_donation :param new_donation: :return: bool """ try: db.session.add(new_donation) db.session.commit() return True except SQLAlchemyError as e: # to put log return False
class EthNotificationEndpoint(db.Model): id = db.Column(db.Integer, primary_key=True) eth_address = db.Column(db.String(255), index=True) device_token = db.Column(db.String(255), index=True) type = db.Column(db.Enum(EthNotificationTypes)) active = db.Column(db.Boolean()) verified = db.Column(db.Boolean()) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now()) expires_at = db.Column(db.DateTime(timezone=True))
class Action(BaseModel): __tablename__ = "actions" id = db.Column(db.Integer, primary_key=True) holding_id = db.Column(db.Integer, db.ForeignKey("holdings.id"), nullable=False) type = db.Column(db.Enum(ActionType)) created_utc = db.Column(db.DateTime, default=dt.utcnow) @property def player(self): return self.holding.player
class Task(db.Model): __tablename__ = 'tasks' id = db.Column(db.String(255), primary_key=True) user_id = db.Column(db.String(255), db.ForeignKey('users.id'), nullable=False) name = db.Column(db.String(20), nullable=False) date = db.Column(db.DateTime, nullable=False) progress_status = db.Column(db.Enum('waiting', 'ongoing', 'finished', 'failed'), nullable=False) length = db.Column(db.Integer, nullable=False) analysis_report = db.relationship('AnalysisReport', backref='tasks', lazy='dynamic') docs = db.relationship('JudicialDoc', backref='tasks', lazy='dynamic')
class BettingRound(BaseModel): __tablename__= "betting_rounds" id = db.Column(db.Integer, primary_key=True) hand_id = db.Column(db.Integer, db.ForeignKey("hands.id"), nullable=False) bettor_id = db.Column(db.Integer, db.ForeignKey("players.id")) round_num = db.Column(db.Integer, nullable=False) bet = db.Column(db.Integer) # The highest current bet for round raise_amt = db.Column(db.Integer) blind_leading = db.Column(db.Boolean, nullable=False, default=False) # Is the leading bet a blind? state = db.Column(db.Enum(State), nullable=False, default=State.OPEN) created_utc = db.Column(db.DateTime, default=dt.utcnow) bets = db.relationship("Bet", backref="betting_round", lazy="dynamic") bettor = db.relationship("Player", lazy=True) @property def sum(self): bets = self.bets.all() if not bets: return 0 return sum([bet.amount for bet in bets]) def player_bets(self, player): return self.bets.filter_by(player_id=player.id).all() def sum_player_bets(self, player): player_bets = self.player_bets(player) if not player_bets: return 0 return sum([bet.amount for bet in player_bets]) def new_bet(self, player, amount): if amount > player.balance: raise InsufficientBalanceError if amount != 0: player.update(balance=player.balance - amount) return Bet.create(player_id=player.id, betting_round_id=self.id, amount=amount) def close(self): self.state = State.CLOSED self.hand.active_betting_round = None self.save()
class Organization(BaseModel): """ Organization model. Args: BaseModel : Base model. """ __tablename__ = 'organization' name = db.Column(db.String(256), unique=True) name_slug = db.Column(db.String(256), unique=True) address = db.Column(db.String(256)) status = db.Column(db.Enum(OrganizationStatus)) def __repr__(self): return '<Organization %s>' % self.name
class TransferModel(db.Model): __tablename__ = "transfers" id = db.Column(db.Integer, primary_key=True) year = db.Column(db.Integer, nullable=False) month = db.Column( db.Enum("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december", name="transfer_month")) total_mmk = db.Column(db.Float()) total_jpy = db.Column(db.Float()) def __init__(self, year: int, month: str, total_mmk: float, total_jpy: float) -> None: self.year = year self.month = month self.total_mmk = total_mmk self.total_jpy = total_jpy def __repr__(self): return f"<Transfer record for {self.month}>" @staticmethod def create_transfer(new_transfer) -> bool: """ create new transfer record :param new_transfer: :return: bool """ try: db.session.add(new_transfer) db.session.commit() return True except SQLAlchemyError as e: # to put log return False
class Device(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), unique=True, nullable=False) description = db.Column(db.String(120)) time_off = db.Column(db.DateTime, unique=True) device_type = db.Column(db.Enum(DeviceType), nullable=False) device_id = db.Column(db.String(120), unique=True, nullable=False) state = db.Column(db.Boolean, default=False) def __repr__(self): return '<Device %r>' % self.name @hybrid_property def schedules(self): return get_jobs(self) @hybrid_property def schedules_count(self): return len(get_jobs(self))
class Pot(BaseModel): """ A collection of bets to be won in a hand of poker TODO - Allow multiple pots per hand (sidepots) """ __tablename__ = "pots" __table_args__ = ( db.CheckConstraint("(state != 'CLOSED' AND winner_id IS NULL) OR " "(state = 'CLOSED' and winner_id IS NOT NULL)"), ) id = db.Column(db.Integer, primary_key=True) hand_id = db.Column(db.Integer, db.ForeignKey("hands.id"), nullable=False) parent_id = db.Column(db.Integer, db.ForeignKey("pots.id"), nullable=True) winner_id = db.Column(db.Integer, db.ForeignKey("players.id"), nullable=True) amount = db.Column(db.Integer, default=0) state = db.Column(db.Enum(PotState), nullable=False, default=State.OPEN) created_utc = db.Column(db.DateTime, default=dt.utcnow) parent = db.relationship("Pot", backref="children", remote_side=[id], lazy=True) winner = db.relationship("Player", lazy=True) eligible_players = db.relationship("Player", secondary=pots_players, lazy=True) @property def closed(self): return self.state == PotState.CLOSED def split(self, children=2): self.update(state=PotState.SPLIT) for child in range(children): amount = self.amount // children if child == 0: # Add remainder of uneven pot to first child amount += self.amount % children Pot.create(hand_id=self.hand.id, parent_id=self.id, amount=amount) return self.children def remove_player(self, player): self.eligible_players.remove(player) self.save()
class StatusCategoryStatusMapping(db.Model): __tablename__ = "status_category_status_mappings" id = db.Column(db.Integer, primary_key=True, nullable=False) activity_id = db.Column(db.Integer, db.ForeignKey("activities.activity_id"), nullable=True) status = db.Column(db.String, nullable=False) status_category = db.Column(db.Enum(StatusCategory), nullable=False) activity = db.relationship("Activity", backref="status_mappings") __table_args__ = ( db.UniqueConstraint("activity_id", "status"), db.Index( "ix_status_activity_id_null", "status", unique=True, postgresql_where=(activity_id.is_(None)), ), )
class Job(BaseModel): """Job model""" __tablename__ = 'job' title = db.Column(db.String(256)) description = db.Column(db.String(256), nullable=True) start_date = db.Column(db.Date, nullable=True) completion_date = db.Column(db.Date, nullable=True) status = db.Column(db.Enum(JobStatus), default=JobStatus.NOT_STARTED) engagement_id = db.Column(UUID, db.ForeignKey('engagement.id')) engagement = relationship('Engagement') organization_id = db.Column(UUID, db.ForeignKey('organization.id')) organization = relationship('Organization') manager_id = db.Column(UUID, nullable=True) def __repr__(self): return '<Job %s>' % self.title
class JudicialDoc(db.Model): """Represents judicial documents.""" # Set the name for table __tablename__ = 'judicial_docs' id = db.Column(db.String(50), primary_key=True) user_id = db.Column(db.String(255), db.ForeignKey('users.id'), nullable=False) task_id = db.Column(db.String(255), db.ForeignKey('tasks.id')) docname = db.Column(db.String(255), nullable=False) date = db.Column(db.DateTime, nullable=False) check_status = db.Column(db.Enum('untested', 'waiting', 'ongoing', 'finished', 'wrong', 'accident'), nullable=False) length = db.Column(db.INTEGER, nullable=False) loc = db.Column(db.String(200), nullable=False) province = db.Column(db.String(10)) writ_date = db.Column(db.String(10)) reports = db.relationship('Report', backref='judicial_docs', lazy='dynamic')
class Reservation(db.Model): id = db.Column(db.Integer, primary_key=True) date_from = db.Column(db.DateTime, nullable=False) date_to = db.Column(db.DateTime) room_id = db.Column(db.Integer, db.ForeignKey('room.id'), nullable=False) status = db.Column(db.Enum(Status), nullable=False) renter_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) def __init__(self, date_from, date_to, status, renter_id): self.date_from = date_from self.date_to = date_to self.status = status self.renter_id = renter_id def to_dict(self): if self.date_to is None: r = {'date_from': self.date_from.strftime("%Y-%m-%d"), 'date_to': self.date_to, 'status': self.status.value} else: r = {'date_from': self.date_from.strftime("%Y-%m-%d"), 'date_to': self.date_to.strftime("%Y-%m-%d"), 'status': self.status.value} return r
class Person(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) email = db.Column(db.String(255)) organization = db.Column(db.String(255)) curriculum = db.Column(db.Text) photo = db.Column(db.String(255)) document = db.Column(db.String(255)) passport = db.Column(db.String(255)) country_id = db.Column(db.Integer, db.ForeignKey('country.id')) city_id = db.Column(db.Integer, db.ForeignKey('cities.id')) country = db.relationship(Country) city = db.relationship(City) phone = db.Column(db.String(255)) # Male, Female, Undefined sex = db.Column(db.Enum(u'M', u'F', u'U', name='sex_enum')) password = db.Column(db.String(100)) profile_id = db.Column(db.Integer, db.ForeignKey('profile.id')) profile = db.relationship(Profile)
class TransferModel(db.Model): __tablename__ = "transfers" id = db.Column(db.Integer, primary_key=True) year = db.Column(db.Integer, nullable=False) month = db.Column( db.Enum("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december", name="transfer_month")) total_mmk = db.Column(db.Float()) total_jpy = db.Column(db.Float()) def __init__(self, year: int, month: str, total_mmk: float, total_jpy: float) -> None: self.year = year self.month = month self.total_mmk = total_mmk self.total_jpy = total_jpy def __repr__(self): return f"<Transfer record for {self.month}>" def as_dict(self) -> Dict[str, Any]: """ Return object data in easily serializable format """ return { "id": self.id, "year": self.year, "month": self.month, "total_mmk": self.total_mmk, "total_jpy": self.total_jpy } @staticmethod def create_transfer(new_transfer: TransferModel) -> bool: """ create new transfer record :param new_transfer: :return: bool """ try: db.session.add(new_transfer) db.session.commit() return new_transfer.id except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def get_all_transfers(page: int, per_page: int = 20) -> Pagination: """ get all Transfer records :param: int :param: per_page :return: Transfer list """ try: return db.session.query(TransferModel).paginate(page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def get_transfer_by_id(transfer_id: int) -> TransferModel: """ get all transfer records :return: transfer list """ try: return db.session.query(TransferModel).filter( TransferModel.id == transfer_id).first() except SQLAlchemyError as error: raise error @staticmethod def delete_transfer_by_id(transfer_id: int) -> bool: """ delete transfer by id :param transfer_id: :return: """ try: if not db.session.query(TransferModel).filter( TransferModel.id == transfer_id).delete(): return False db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def update_transfer(transfer_id: int, transfer: TransferModel) -> bool: """ update transfer info by id :param transfer_id: :param transfer: :return: bool """ try: update_transfer = db.session.query(TransferModel).filter( TransferModel.id == transfer_id).first() if not update_transfer: raise SQLCustomError( description="No record for requested transfer") update_transfer.year = transfer.year update_transfer.month = transfer.month update_transfer.total_mmk = transfer.total_mmk update_transfer.total_jpy = transfer.total_jpy db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error
class UserModel(db.Model): """ User Model class with table column definition """ __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) display_name = db.Column(db.String(), nullable=False) username = db.Column(db.String(), unique=True, nullable=False) email = db.Column(db.String(), unique=True, nullable=False) hashed_password = db.Column(db.Text(), nullable=True) role = db.Column(db.Enum("sub_admin", "donator", "admin", name="role")) country = db.Column(db.String(), nullable=True) donation_active = db.Column(db.Boolean, default=False) address_id = db.Column(db.Integer, db.ForeignKey("addresses.id"), nullable=False) address = relationship("AddressModel", foreign_keys=[address_id]) def __init__(self, display_name: str, username: str, email: str, address_id: int, role: str, country: str, hashed_password: str = None, donation_active: bool = False) -> None: self.display_name = display_name self.username = username self.email = email self.address_id = address_id self.hashed_password = hashed_password self.role = role self.country = country self.donation_active = donation_active def __repr__(self): return f"<User {self.username}>" def as_dict(self) -> Dict[str, Any]: """ Return object data in easily serializable format """ return { "id": self.id, "display_name": self.display_name, "username": self.username, "email": self.email, "formatted_address": self.address.format_address(), "address": self.address.as_dict(), "role": self.role, "country": self.country, "donation_active": self.donation_active } @staticmethod def create_user(new_user: UserModel) -> int: """ create new users :param new_user: :return: created user id """ try: db.session.add(new_user) db.session.commit() return new_user.id except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def update_user(user_id: int, user: UserModel) -> bool: """ update user info by id :param user_id: :param user: :return: bool """ try: target_user = db.session.query(UserModel).get(user_id) if not target_user: raise SQLCustomError("No record for requested school") target_user.display_name = user.display_name target_user.username = user.username target_user.email = user.email target_user.country = user.country target_user.donation_active = user.donation_active db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def delete_user(user_id: int) -> bool: """ delete user by id :param user_id: :return: bool """ try: if not db.session.query(UserModel).filter( UserModel.id == user_id).delete(): return False db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def get_user_by_id(user_id: int) -> UserModel: """ get user by id :param user_id: :return: user info """ try: return db.session.query(UserModel).get(user_id) except SQLAlchemyError as error: raise error @staticmethod def get_users_by_address_ids(address_ids: tuple) -> List[UserModel]: """ get user by ids :param address_ids: :return: user infos """ try: return db.session.query(UserModel).filter( UserModel.address_id.in_(address_ids)).all() except SQLAlchemyError as error: raise error @staticmethod def get_user_by_email(email: str) -> UserModel: """ get user by email :param email: :return: user info """ try: return db.session.query(UserModel).filter( UserModel.email == email).first() except SQLAlchemyError as error: raise error @staticmethod def get_user_by_username(username: str) -> UserModel: """ get user by username :param username: :return: user info """ try: return db.session.query(UserModel).filter( UserModel.username == username).first() except SQLAlchemyError as error: raise error @staticmethod def get_users_by_query(page: int, query: str, per_page: int = 20) -> Pagination: """ get users by name (as name is not unique, multiple records can be returned) :param page: :param query: :param per_page int :return: user info list """ try: return db.session.query(UserModel).\ join(AddressModel).filter(or_(UserModel.display_name.ilike('%' + query + '%'), UserModel.email.ilike('%' + query + '%'))).paginate( page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def get_all_users(page: int = 1, per_page: int = 20) -> Pagination: """ get all users :page integer :per_page int :return: users list of dict """ try: return db.session.query(UserModel).join(AddressModel).paginate( page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def get_users_by_role(page: int, role: str, per_page: int = 20) -> Pagination: """ get all users by role :params integer :role str :per_page int :return: users list of Pagination """ try: return db.session.query(UserModel).join(AddressModel).filter( UserModel.role == role).paginate(page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def get_users_by_country(page: int, country: str, per_page: int = 20) -> Pagination: """ get all users by country :params integer :country str :per_page int :return: users list of dict """ try: return db.session.query(UserModel).join(AddressModel).filter( UserModel.country == country).paginate(page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def get_users_by_role_country(page: int, role: str, country: str, per_page: int = 20) -> Pagination: """ get all users by role and country :params page :params role :country role :per_page int :return: user info list """ try: return db.session.query(UserModel).join(AddressModel).filter( and_(UserModel.country == country, UserModel.role == role)).paginate(page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def get_all_user_address(page: int = 1, per_page: int = 20) -> Pagination: """ get all user address for get all address API :params page :return Pagination Object """ try: return db.session.query(AddressModel, UserModel). \ filter(AddressModel.id == UserModel.address_id).filter( AddressModel.type == "user").paginate(page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def change_password(user_id: int, new_pwd: str) -> bool: """ change password by userid :param user_id: :param new_pwd: :return: bool """ try: db.session.query(UserModel).filter(UserModel.id == user_id).\ update({UserModel.hashed_password: new_pwd}) db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def change_password(user_id, new_pwd) -> bool: """ change password by userid :param user_id: :param new_pwd: :return: bool """ try: db.session.query(UserModel).filter(UserModel.id == user_id).\ update({UserModel.hashed_password: new_pwd}) db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error
class DonationModel(db.Model): __tablename__ = "donations" id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) attendance_id = db.Column(db.Integer, db.ForeignKey("attendances.id"), nullable=False) transfer_id = db.Column(db.Integer, db.ForeignKey("transfers.id"), nullable=True) year = db.Column(db.Integer, nullable=False) month = db.Column( db.Enum("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december", name="month")) mmk_amount = db.Column(db.Float()) jpy_amount = db.Column(db.Float()) paid_at = db.Column(db.DateTime(), nullable=True) def __init__(self, user_id: int, attendance_id: int, transfer_id: int, year: int, month: str, mmk_amount: float, jpy_amount: float, paid_at: datetime) -> None: self.user_id = user_id self.attendance_id = attendance_id self.transfer_id = transfer_id self.year = year self.month = month self.mmk_amount = mmk_amount self.jpy_amount = jpy_amount self.paid_at = paid_at def __repr__(self): return f"<Donation Records for user_id {self.user_id}>" def donation_dict(self, user: UserModel, student: StudentModel): """ Return object data for viewing easily serializable format :param user: :param student: :return: """ return { "id": self.id, "user": user.as_dict(), "year": self.year, "month": self.month, "student": student.student_dict(), "mmk_amount": self.mmk_amount, "jpy_amount": self.jpy_amount, "status": "pending" if self.paid_at is None else "paid" } @staticmethod def create_donation(new_donation) -> int: """ create new_donation :param new_donation: :return: int """ try: db.session.add(new_donation) db.session.commit() return new_donation.id except SQLAlchemyError as error: raise error @staticmethod def get_all_donations(page) -> Pagination: """ get all donation records :return: donation list """ try: return db.session.query(DonationModel, UserModel, StudentModel). \ filter(DonationModel.user_id == UserModel.id). \ filter(DonationModel.attendance_id == AttendanceModel.id). \ filter(AttendanceModel.id == StudentModel.id).paginate(page=page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def get_donation_by_id(donation_id: int) -> List[DonationModel]: """ get all donation records :param donation_id :return: donation list """ try: return db.session.query(DonationModel, UserModel, StudentModel). \ filter(DonationModel.user_id == UserModel.id). \ filter(DonationModel.attendance_id == AttendanceModel.id). \ filter(AttendanceModel.id == StudentModel.id). \ filter(DonationModel.id == donation_id) except SQLAlchemyError as error: raise error @staticmethod def delete_donation_by_id(donation_id: int) -> bool: """ delete donation by id :param donation_id: :return: """ try: if not db.session.query(DonationModel).filter( DonationModel.id == donation_id).delete(): return False db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def update_donation(donation_id: int, donation: DonationModel) -> bool: """ update donation info by id :param donation_id: :param donation: :return: bool """ try: target_donation = db.session.query(DonationModel).filter( DonationModel.id == donation_id).first() if not target_donation: raise SQLCustomError("No record for requested donation") target_donation.user_id = donation.user_id target_donation.attendance_id = donation.attendance_id target_donation.transfer_id = donation.transfer_id target_donation.month = donation.month target_donation.year = donation.year target_donation.mmk_amount = donation.mmk_amount target_donation.jpy_amount = donation.jpy_amount target_donation.paid_at = donation.paid_at db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error
class UserModel(db.Model): """ User Model class with table column definition """ __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(), nullable=False) email = db.Column(db.String(), unique=True, nullable=False) hashed_password = db.Column(db.Text(), nullable=True) role = db.Column(db.Enum("sub_admin", "donator", "admin", name="role")) country = db.Column(db.Enum("jp", "mm", "sg", "th", name="country")) address_id = db.Column(db.Integer, db.ForeignKey("addresses.id"), nullable=False) address = relationship("AddressModel", foreign_keys=[address_id]) def __init__(self, name: str, email: str, address_id: int, role: str, country: str, hashed_password: str = None) -> None: self.name = name self.email = email self.address_id = address_id self.hashed_password = hashed_password self.role = role self.country = country def __repr__(self): return f"<User {self.name}>" def as_dict(self) -> Dict[str, Any]: """ Return object data in easily serializable format """ return { "id": self.id, "name": self.name, "email": self.email, "formatted_address": self.address.format_address(), "address": self.address.as_dict(), "role": self.role, "country": self.country } @staticmethod def create_user(new_user) -> int: """ create new users :param new_user: :return: created user id """ try: db.session.add(new_user) db.session.commit() return new_user.id except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def update_user(user_id, user) -> bool: """ update user info by id :param user_id: :param user: :return: bool """ try: target_user = db.session.query(UserModel).filter( UserModel.id == user_id).first() if not target_user: raise SQLCustomError("No record for requested school") target_user.name = user.name target_user.email = user.email target_user.address_id = user.address_id target_user.country = user.country db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def delete_user(user_id) -> bool: """ delete user by id :param user_id: :return: bool """ try: if not db.session.query(UserModel).filter( UserModel.id == user_id).delete(): return False db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def get_user_by_id(user_id: int) -> UserModel: """ get user by id :param user_id: :return: user info """ try: return db.session.query(UserModel).filter( UserModel.id == user_id).first() except SQLAlchemyError as error: raise error @staticmethod def get_user_by_email(email: str) -> UserModel: """ get user by email :param email: :return: user info """ try: return db.session.query(UserModel).filter( UserModel.email == email).first() except SQLAlchemyError as error: raise error @staticmethod def get_users_by_name(name) -> List[UserModel]: """ get users by name (as name is not unique, multiple records can be returned) :param name: :return: user info list """ try: return db.session.query(UserModel).join(AddressModel).filter( UserModel.name == name) except SQLAlchemyError as error: raise error @staticmethod def get_all_users() -> List[UserModel]: """ get all users :return: users list of dict """ try: return db.session.query(UserModel).join(AddressModel).all() except SQLAlchemyError as error: raise error
class Hand(BaseModel): __tablename__ = "hands" id = db.Column(db.Integer, primary_key=True) table_id = db.Column(db.Integer, db.ForeignKey("tables.id"), nullable=False) stakes_id = db.Column(db.Integer, db.ForeignKey("stakes.id"), nullable=False) dealer_id = db.Column(db.Integer, db.ForeignKey("players.id"), nullable=False) next_id = db.Column(db.Integer, db.ForeignKey("players.id"), nullable=False) rounds = db.Column(db.Integer, nullable=False) # Number of betting rounds per hand state = db.Column(db.Enum(State), default=State.OPEN) created_utc = db.Column(db.DateTime, default=dt.utcnow) betting_rounds = db.relationship("BettingRound", backref="hand", lazy=True, order_by="BettingRound.id") active_betting_round = db.relationship("BettingRound", secondary=betting_rounds_active, lazy="subquery", uselist=False) pots = db.relationship("Pot", backref="hand", lazy=True, order_by="desc(Pot.created_utc)") holdings = db.relationship("Holding", backref="hand", lazy="dynamic") dealer = db.relationship("Player", lazy=True, foreign_keys="[Hand.dealer_id]") next_to_act = db.relationship("Player", backref="hand", lazy=True, foreign_keys="[Hand.next_id]") stakes = db.relationship("Stakes", lazy=True) @property def player_holdings(self): return sorted(self.holdings.filter_by(is_board=False).all(), key=lambda holding: holding.player.seat) @property def players(self): return [holding.player for holding in self.player_holdings] @property def live_holdings(self): return sorted( self.holdings.filter_by(is_board=False, active=True).all(), key=lambda holding: holding.player.seat) @property def live_players(self): return [holding.player for holding in self.live_holdings] @property def board(self): return self.holdings.filter_by(is_board=True).first() @property def active_pot(self): if not self.pots: return None return self.pots[0] @property def complete(self): return self.state == State.CLOSED @property def pots_paid(self): return [pot for pot in self.pots if pot.closed] @property def winners(self): return [pot.winner for pot in self.pots_paid] @property def blinds_owed(self): if self.stakes.sum_blinds == 0: return False elif self.active_betting_round.round_num != 0: return False return self.active_betting_round.sum < self.stakes.sum_blinds @property def antes_owed(self): return self.active_betting_round.round_num == -1 @property def dealt(self): return self.board is not None def new_betting_round(self): """Start a new betting round for the hand.""" round_num = 0 if self.betting_rounds: # New round num will be one greater than previous round_num = self.betting_rounds[-1].round_num + 1 if round_num > self.rounds - 1: raise InvalidRoundNumberError new_round = BettingRound(hand_id=self.id, round_num=round_num) self.active_betting_round = new_round self.save() return new_round def new_pot(self, players=None): if players is None: players = self.players pot = Pot(hand_id=self.id, amount=0) pot.eligible_players = players pot.save() return pot def new_holding(self, player=None, cards=None, **kwargs): kwargs["player_id"] = None if player is None else player.id kwargs["is_board"] = player is None return Holding.create(hand_id=self.id, cards=cards, **kwargs) def resolve_action(self, action, current_bet, total_bet): ret = {} if action.type == ActionType.FOLD: action.holding.fold() self.remove_player_from_pots(action.player) else: self.active_betting_round.new_bet(action.player, current_bet) if action.type == ActionType.BLIND: # Do not register bettor here to allow for BB option # and correct bet/raise amounts after blinds self.active_betting_round.bet = total_bet self.active_betting_round.raise_amt = total_bet self.active_betting_round.blind_leading = True elif self.active_betting_round.bettor is None or (total_bet > self.active_betting_round.bet): self.active_betting_round.raise_amt = total_bet if self.active_betting_round.bet is not None and not self.active_betting_round.blind_leading: self.active_betting_round.raise_amt = total_bet - self.active_betting_round.bet self.active_betting_round.bet = total_bet self.active_betting_round.bettor = action.player self.active_betting_round.blind_leading = False self.update_next_to_act() hand_complete = len(self.live_holdings) == 1 # Bet has gone around table. Betting round complete. if self.next_to_act == self.active_betting_round.bettor: self.determine_side_pots() # TODO - Rename method? self.active_betting_round.close() ret["round_complete"] = True if not hand_complete: next_seat = determine_next_seat(self.dealer.seat, [player.seat for player in self.live_players]) self.next_to_act = self.table.player_at_seat(next_seat) try: self.new_betting_round() ret["new_round"] = True except InvalidRoundNumberError: # Final round of hand complete hand_complete = True if hand_complete: ret["round_complete"] = True ret["hand_complete"] = True # Copy list so changes to list in loop don't cause problems for pot in list(self.pots): winners = self.determine_winners(players=pot.eligible_players) pots = [pot] if len(winners) > 1: pots = pot.split(children=len(winners)) for winner, won_pot in zip(winners, pots): winner.update(balance=winner.balance + won_pot.amount) won_pot.update(state=PotState.CLOSED, winner=winner) self.close() self.save() return ret def determine_winners(self, players=None): """ Find the player(s) with the most valuable five-card hand, using two hole cards and five community cards. :param players: List of players to be evaluated :return: List of Player objects """ players_and_cards = [(holding.player.id, holding.codes) for holding in self.live_holdings] if players: player_ids = [p.id for p in players] players_and_cards = [d for d in players_and_cards if d[0] in player_ids] winners = determine_winners(players_and_cards, self.board.codes) return [Player.query.get(winner) for winner in winners] def update_next_to_act(self): seats = [holding.player.seat for holding in self.live_holdings] seat = determine_next_seat(self.next_to_act.seat, seats) self.next_to_act = self.table.player_at_seat(seat) return self.next_to_act def close(self): # if any([pot.state == PotState.OPEN for pot in self.pots]): # raise Exception("Can't close a hand with open pots") # elif any([round.state == State.OPEN for round in self.betting_rounds]): # raise Exception("Can't close a hand with open betting rounds") self.state = State.CLOSED self.table.active_hand = None self.save() def remove_player_from_pots(self, player): for pot in self.pots: pot.remove_player(player) def determine_side_pots(self): # TODO - Move poker-specific stuff into poker file folded_bets = [] live_bets = [] for holding in self.player_holdings: # Build separate lists of bets for live and folded hands player = holding.player data = { 'player': player, 'bet': self.active_betting_round.sum_player_bets(player) } if holding.active: live_bets.append(data) else: folded_bets.append(data) live_bets.sort(key=lambda x: x['bet']) # Sort bet ascending while live_bets: bet = live_bets[0]["bet"] live_bets = live_bets[1:] self.active_pot.amount += bet # Take amount of smallest round bet from every player's bets for i in range(len(live_bets)): live_bets[i]["bet"] -= bet self.active_pot.amount += bet # Take either the smallest round bet or the amount folded from folded bets for i in range(len(folded_bets)): folded_bet = min(bet, folded_bets[i]["bet"]) folded_bets[i]["bet"] -= folded_bet self.active_pot.amount += folded_bet # Remove zeroed out bets from lists live_bets = [d for d in live_bets if d["bet"] > 0] folded_bets = [d for d in folded_bets if d["bet"] > 0] if len(live_bets) == 1: # Record negative bet to refund player for overbet self.active_betting_round.new_bet(live_bets[0]["player"], -live_bets[0]["bet"]) live_bets = [] elif len(live_bets) > 1: self.new_pot([d["player"] for d in live_bets]) def deal(self, hand_type, players): poker_hand = hand_type(num_players=len(players)) self.new_holding(cards=poker_hand.board) for i, poker_holding in enumerate(poker_hand.holdings): self.player_holdings[i].add_cards(poker_holding) self.save() @property def dealt(self): return len(self.player_holdings[0].cards) > 0
class AttendanceModel(db.Model): __tablename__ = "attendances" id = db.Column(db.Integer, primary_key=True) student_id = db.Column(db.Integer, db.ForeignKey("students.id"), nullable=False) school_id = db.Column(db.Integer, db.ForeignKey("schools.id"), nullable=False) grade = db.Column( db.Enum("KG", "G-1", "G-2", "G-3", "G-4", "G-5", "G-6", "G-7", "G-8", "G-9", "G-10", "G-11", "G-12", name="grade")) year = db.Column(db.Integer, nullable=False) enrolled_date = db.Column(db.Date(), nullable=True) school = relationship("SchoolModel", foreign_keys=[school_id]) student = relationship("StudentModel", foreign_keys=[student_id]) def __init__(self, student_id: str, school_id: str, grade: str, year: str, enrolled_date: date) -> None: self.student_id = student_id self.school_id = school_id self.grade = grade self.year = year self.enrolled_date = enrolled_date def __repr__(self): return f"<Attendance for student id: {self.student_id}>" def attendance_dict(self, school: SchoolModel, student: StudentModel): """ Return object data for viewing easily serializable format :param school: :param student: :return: """ return { "id": self.id, "grade": self.grade, "year": self.year, "enrolled_date": self.enrolled_date.strftime("%d-%m-%Y"), "school": school.school_dict(), "student": student.student_dict() } @staticmethod def create_attendance(new_attendance) -> bool: """ create new_attendance :param new_attendance: :return: bool """ try: db.session.add(new_attendance) db.session.commit() return new_attendance.id except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def get_all_attendance() -> List[AttendanceModel]: """ get all Attendance records :return: Attendance list """ try: return db.session.query(AttendanceModel, SchoolModel, StudentModel).\ filter(AttendanceModel.school_id == SchoolModel.id).\ filter(AttendanceModel.student_id == StudentModel.id).all() except SQLAlchemyError as error: raise error @staticmethod def get_attendance_by_id(attendance_id: int) -> List[AttendanceModel]: """ get all Attendance records :param attendance_id :return: Attendance list """ try: return db.session.query(AttendanceModel, SchoolModel, StudentModel). \ filter(AttendanceModel.school_id == SchoolModel.id). \ filter(AttendanceModel.student_id == StudentModel.id).\ filter(AttendanceModel.id == attendance_id) except SQLAlchemyError as error: raise error @staticmethod def delete_attendance_by_id(attendance_id: int) -> bool: """ delete Attendance by id :param attendance_id: :return: """ try: if not db.session.query(AttendanceModel).filter( AttendanceModel.id == attendance_id).delete(): return False db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def update_attendance(attendance_id: int, attendance: AttendanceModel) -> bool: """ update attendance info by id :param attendance_id: :param attendance: :return: bool """ try: target_attendance = db.session.query(AttendanceModel).filter( AttendanceModel.id == attendance_id).first() if not target_attendance: raise SQLCustomError("No record for requested attendance") target_attendance.student_id = attendance.student_id target_attendance.school_id = attendance.school_id target_attendance.grade = attendance.grade target_attendance.year = attendance.year target_attendance.enrolled_date = attendance.enrolled_date db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error
class AddressModel(db.Model): """ address Model class with table column definition """ __tablename__ = "addresses" id = db.Column(db.Integer, primary_key=True) division = db.Column(db.UnicodeText()) district = db.Column(db.UnicodeText()) township = db.Column(db.UnicodeText()) street_address = db.Column(db.UnicodeText()) type = db.Column(db.Enum("user", "student", "school", name="addresses_types"), default="user", nullable=False) def __repr__(self): return f"<Address {self.format_address()}>" def __init__(self, division: str, district: str, township: str, street_address: str, type: str = "user") -> None: self.division = division self.district = district self.township = township self.street_address = street_address self.type = type def format_address(self): """ format address to user readable format :return: """ return ", ".join( filter(lambda x: x is not None and x != "", [ self.street_address, self.township, self.district, self.division ])) def as_dict(self) -> Dict[str, Any]: """ Return object data in easily serializable format """ return { "id": self.id, "division": self.division, "type": self.type, "district": self.district, "township": self.township, "street_address": self.street_address } @staticmethod def create_address(new_address: AddressModel, flush: bool = False) -> int: """ create new_address for student flush is true if user,school,student create else false (for rollback) :param new_address: :param flush: :return: bool """ try: db.session.add(new_address) db.session.flush() if flush else db.session.commit() return new_address.id except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def update_address(address_id: int, address: AddressModel) -> bool: """ update address info by id :param address_id: :param address: :return: bool """ try: target_address = db.session.query(AddressModel).filter( AddressModel.id == address_id).first() if not target_address: raise SQLCustomError("No record for requested address") target_address.division = address.division target_address.district = address.district target_address.township = address.township target_address.street_address = address.street_address target_address.type = address.type db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def get_address_by_id(address_id: int) -> AddressModel: """ get address by id :param address_id: :return: address info """ try: return db.session.query(AddressModel).filter( AddressModel.id == address_id).first() except SQLAlchemyError as error: raise error @staticmethod def get_all_addresses(page: int = 1, per_page: int = 20) -> Pagination: """ get all address record :param page: :param per_page: :return: get all address info """ try: return db.session.query(AddressModel).paginate(page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def get_all_addresses_by_type(page: int, per_page: int, address_type: str) -> Pagination: """ get all address record by address type :param page: :param per_page: :param address_type: :return: get all address info by address type """ try: return db.session.query(AddressModel).filter( AddressModel.type == address_type).paginate(page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error @staticmethod def delete_address(address_id: int) -> bool: """ delete address by id :param address_id: :return: bool """ try: if not db.session.query(AddressModel).filter( AddressModel.id == address_id).delete(): return False db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def search_address_by_query(page: int, per_page: int, query: str) -> Pagination: """ delete address by id :param page: :param per_page: :param query: :return: Pagination """ try: return db.session.query(AddressModel).filter( or_( AddressModel.division.ilike('%' + query + '%'), AddressModel.district.ilike('%' + query + '%'), AddressModel.township.ilike('%' + query + '%'), AddressModel.street_address.ilike('%' + query + '%'), )).paginate(page=page, per_page=per_page, error_out=False) except SQLAlchemyError as error: raise error
class Users(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(50), unique=True, nullable=False) name = db.Column(db.String(70)) email = db.Column(db.String(255), unique=True, nullable=False) password = db.Column(db.String(255), nullable=False) account_type = db.Column(db.Enum(AccountType)) files = db.relationship('UploadedFiles', secondary='file_access', backref=db.backref('user', lazy='dynamic')) sign_up_timestamp = db.Column(db.DateTime(timezone=True)) def __init__(self, username, email, password, name=None, account_type=AccountType.user, sign_up_timestamp=None): self.name = name self.username = username self.email = email self.password = generate_password_hash(password) self.account_type = account_type tz = get_localzone() if sign_up_timestamp is None: sign_up_timestamp = tz.localize(datetime.now(), is_dst=None) sign_up_timestamp = sign_up_timestamp.astimezone(pytz.UTC) if sign_up_timestamp.tzinfo is None: sign_up_timestamp = pytz.utc.localize(sign_up_timestamp, is_dst=None) self.sign_up_timestamp = sign_up_timestamp def __repr__(self): return '<User {username}>'.format(username=self.username) """ @property def password(self): raise AttributeError('Password can not be accessed directly!') @password.setter def password(self, new_password): self._password = generate_password_hash(new_password) @property def name(self): return self.name @name.setter def name(self, new_name): self._name = new_name @property def email(self): return self.email @email.setter def email(self, new_email): self._email = new_email @property def account_type(self): return self.account_type @account_type.setter def account_type(self, new_account_type): self._account_type = new_account_type """ @property def is_admin(self): return self.account_type == AccountType.admin def is_password_valid(self, password): return check_password_hash(self.password, password) def has_role(self, account_type): return self.account_type == account_type or self.is_admin @db.reconstructor def may_the_timezone_be_with_it(self): """ Localize the timestamp to utc """ self.sign_up_timestamp = pytz.utc.localize(self.sign_up_timestamp, is_dst=None)
class AddressModel(db.Model): """ address Model class with table column definition """ __tablename__ = "addresses" id = db.Column(db.Integer, primary_key=True) division = db.Column(db.Enum("yangon", "ayeyarwady", "chin", "kachin", "kayah", "kayin", "mon", "rakhine", "shan", "bago", "magway", "mandalay", "sagaing", "tanintharyi", name="division")) district = db.Column(db.UnicodeText()) township = db.Column(db.UnicodeText()) street_address = db.Column(db.UnicodeText()) type = db.Column(db.Enum("user", "student", "school", name="addresses_types"), default="user", nullable=False) def __repr__(self): return f"<Address {self.format_address()}>" def __init__(self, division: str, district: str, township: str, street_address: str, type: str = "user") -> None: self.division = division self.district = district self.township = township self.street_address = street_address self.type = type def format_address(self): """ format address to user readable format :return: """ return ", ".join(filter(lambda x: x is not None and x != "", [self.street_address, self.township, self.district, self.division])) def as_dict(self) -> Dict[str, Any]: """ Return object data in easily serializable format """ return { "id": self.id, "division": self.division, "district": self.district, "township": self.township, "street_address": self.street_address } def address_type_dict(self, obj): """ Return object data for viewing easily serializable format :param obj: addressable object from query :return: """ return { "id": self.id, "addressable": { "id": obj.id, "name": obj.name, "type": self.type }, "division": self.division, "district": self.district, "township": self.township, "street_address": self.street_address, } @staticmethod def create_address(new_address) -> (int, bool): """ create new_address for student :param new_address: :return: bool """ try: db.session.add(new_address) db.session.commit() return new_address.id except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def update_address(address_id: int, address) -> bool: """ update address info by id :param address_id: :param address: :return: bool """ try: target_address = db.session.query(AddressModel).filter(AddressModel.id == address_id).first() if not target_address: raise SQLCustomError("No record for requested address") target_address.division = address.division target_address.district = address.district target_address.township = address.township target_address.street_address = address.street_address target_address.type = address.type db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error @staticmethod def get_address_by_id(address_id: int) -> AddressModel: """ get address by id :param address_id: :return: address info """ try: return db.session.query(AddressModel).filter(AddressModel.id == address_id).first() except SQLAlchemyError as error: raise error @staticmethod def delete_address(address_id) -> bool: """ delete address by id :param address_id: :return: bool """ try: if not db.session.query(AddressModel).filter(AddressModel.id == address_id).delete(): return False db.session.commit() return True except SQLAlchemyError as error: db.session.rollback() raise error
class User(db.Model): __tablename__ = "users" class Ranks(enum.Enum): # with minimal Elo rating D7 = "Seven Dan" # Elo 2700+ D6 = "Six Dan" D5 = "Five Dan" # Elo 2500 D4 = "Four Dan" D3 = "Three Dan" D2 = "Two Dan" D1 = "One Dan" K1 = "One Kyu" # Elo 2000 K2 = "Two Kyu" K3 = "Three Kyu" K4 = "Four Kyu" K5 = "Five Kyu" K6 = "Six Kyu" # Elo 1500 K7 = "Seven Kyu" K8 = "Eight Kyu" K9 = "Nine Kyu" K10 = "Ten Kyu" K11 = "Eleven Kyu" # ELo 1000 K12 = "Twelve Kyu" K13 = "Thirteen Kyu" K14 = "Fourteen Kyu" K15 = "Fifteen Kyu" K16 = "Sixteen Kyu" # Elo 500 K17 = "Seventeen Kyu" K18 = "Eighteen Kyu" K19 = "Nineteen Kyu" K20 = "Twenty Kyu" K21 = "Twenty-One Kyu" # Elo 0 K22 = "Twenty-Two Kyu" K23 = "Twenty-Three Kyu" K24 = "Twenty-Four Kyu" K25 = "Twenty-Five Kyu" K26 = "Twenty-Six Kyu" # Elo -500 K27 = "Twenty-Seven Kyu" K28 = "Twenty-Eight Kyu" K29 = "Twenty-Nine Kyu" K30 = "Thirty Kyu" # Elo -900 UR = "Unknown Rank" id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(255), unique=True, nullable=False, autoincrement=True) email = db.Column(db.String(255), unique=True, nullable=False) password = db.Column(db.String(255), nullable=False) registered_on = db.Column(db.DateTime, nullable=False) admin = db.Column(db.Boolean, nullable=False, default=False) rank = db.Column(db.Enum(Ranks)) elo = db.Column(db.Integer) rank_certainty = db.Column(db.Boolean, nullable=False, default=False) def __init__(self, username, email, password, rank=Ranks.UR, admin=False): self.username = username self.email = email self.password = bcrypt.generate_password_hash(password, 13).decode() self.rank = rank self.registered_on = datetime.datetime.now() self.admin = admin def encode_auth_token(self, user_id): """ Generates the Auth Token :return: string """ try: payload = { 'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=4), 'iat': datetime.datetime.utcnow(), 'user': user_schema.dumps(self) } return jwt.encode(payload, os.environ.get('SECRET_KEY'), algorithm='HS256') except Exception as e: return e @staticmethod def decode_auth_token(auth_token): """ Decodes the auth token :param auth_token: :return: integer|string """ try: payload = jwt.decode(auth_token, os.environ.get('SECRET_KEY')) return payload['user'] except jwt.ExpiredSignatureError: return 'Signature expired. Please log in again.' except jwt.InvalidTokenError: return 'Invalid token. Please log in again.'
class Room(db.Model): id = db.Column(db.Integer, primary_key=True) type = db.Column(db.Enum(RoomTypes)) beds_num = db.Column(db.Integer, nullable=False) baths_num = db.Column(db.Integer, nullable=False) bedrooms_num = db.Column(db.Integer, nullable=False) lounge = db.Column(db.Boolean, nullable=False) description = db.Column(db.Text) smoking_allowed = db.Column(db.Boolean, nullable=False) pets_allowed = db.Column(db.Boolean, nullable=False) events_allowed = db.Column(db.Boolean, nullable=False) wireless_internet = db.Column(db.Boolean, nullable=False) air_condition = db.Column(db.Boolean, nullable=False) refrigerator = db.Column(db.Boolean, nullable=False) kitchen = db.Column(db.Boolean, nullable=False) tv = db.Column(db.Boolean, nullable=False) parking = db.Column(db.Boolean, nullable=False) elevator = db.Column(db.Boolean, nullable=False) lat_coordinate = db.Column(db.Float, nullable=False) long_coordinate = db.Column(db.Float, nullable=False) address = db.Column(db.String(50), nullable=False) transport_info = db.Column(db.String(100)) persons_num = db.Column(db.Integer, nullable=False) standard_cost = db.Column(db.Float, nullable=False) add_persons_cost = db.Column(db.Float) rating = db.Column(db.Float) title = db.Column(db.String(30), nullable=False) area = db.Column(db.Float, nullable=False) min_stay = db.Column(db.Integer, nullable=False) listingid = db.Column(db.Integer) owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) images = db.relationship('Image', backref='room', lazy=True) reviews = db.relationship('Review', backref='room', lazy=True) reservations = db.relationship('Reservation', backref='room', lazy=True) threads = db.relationship('Thread', backref='room', lazy=True) @hybrid_property def rating(self): r_sum = 0 reviews_num = len(self.reviews) if reviews_num == 0: return 0 for r in self.reviews: r_sum = r_sum + r.rating return r_sum / reviews_num def __init__(self, rt, beds_num, baths_num, bedr_num, lounge, desc, smoking_all, pets_all, events_all, wifi, ac, refrigerator, kitchen, tv, parking, elevator, latitude, longitude, address, tran_info, pers_num, standard_cost, add_prs_cost, title, area, min_stay, owner_id, listing_id=-1): self.type = rt self.beds_num = beds_num self.baths_num = baths_num self.bedrooms_num = bedr_num self.lounge = lounge self.description = desc self.smoking_allowed = smoking_all self.pets_allowed = pets_all self.events_allowed = events_all self.wireless_internet = wifi self.air_condition = ac self.refrigerator = refrigerator self.kitchen = kitchen self.tv = tv self.parking = parking self.elevator = elevator self.lat_coordinate = latitude self.long_coordinate = longitude self.address = address self.transport_info = tran_info self.persons_num = pers_num self.standard_cost = standard_cost self.add_persons_cost = add_prs_cost self.title = title self.area = area self.min_stay = min_stay self.listingid = listing_id self.owner_id = owner_id def to_dict_all(self): images = [] for i in self.images: image_dict = i.to_dict() images.append(image_dict) public_owner = User.query.filter_by(id=self.owner_id).first() public_owner_id = public_owner.public_id r = { 'Id': self.id, 'type': self.type, 'beds_number': self.beds_num, 'baths_number': self.baths_num, 'lounge': self.lounge, 'description': self.description, 'wireless_internet': self.wireless_internet, 'air_condition': self.air_condition, 'refrigerator': self.refrigerator, 'kitchen': self.kitchen, 'tv': self.tv, 'parking': self.parking, 'elevator': self.elevator, 'location': [self.lat_coordinate, self.long_coordinate], 'smoking_allowed': self.smoking_allowed, 'pets_allowed': self.pets_allowed, 'events_allowed': self.events_allowed, 'min_stay': self.min_stay, 'area': self.area, 'address': self.address, 'transport_info': self.transport_info, 'standard_cost': self.standard_cost, 'add_persons_cost': self.add_persons_cost, 'title': self.title, 'persons_number': self.persons_num, 'rating': self.rating, 'cost_per_day': self.standard_cost, 'images': images, 'bedrooms_number': self.bedrooms_num, 'reviews_num': len(self.reviews), 'public_owner_id': public_owner_id, 'owner_name': public_owner.fname + ' ' + public_owner.surname } return r def to_dict_host_short(self): r = { 'title': self.title, 'cost_per_day': self.standard_cost, 'rating': self.rating, 'address': self.address, 'reviews_number': len(self.reviews), 'location': [self.lat_coordinate, self.long_coordinate], 'id': self.id, 'listingid': self.listingid } if len(self.images) == 0: r['thumbnail'] = '' else: r['thumbnail'] = self.images[0].source return r def to_dict_short(self): r = { 'id': self.id, 'type': self.type, 'beds_number': self.beds_num, 'wireless_internet': self.wireless_internet, 'air_condition': self.air_condition, 'refrigerator': self.refrigerator, 'kitchen': self.kitchen, 'tv': self.tv, 'parking': self.parking, 'elevator': self.elevator, 'title': self.title, 'persons_number': self.persons_num, 'rating': self.rating, 'cost_per_day': self.standard_cost, 'listingid': self.listingid, 'reviews_num': len(self.reviews) } if len(self.images) == 0: r['image_src'] = '' else: r['image_src'] = self.images[0].source return r return r def update(self, data): self.type = RoomTypes(data['type']) self.beds_num = data['beds_number'] self.baths_num = data['baths_number'] self.bedrooms_num = data['bedrooms_number'] self.lounge = data['lounge'] self.description = data['description'] self.smoking_allowed = data['smoking_allowed'] self.pets_allowed = data['pets_allowed'] self.events_allowed = data['events_allowed'] self.wireless_internet = data['wireless_internet'] self.air_condition = data['air_condition'] self.refrigerator = data['refrigerator'] self.kitchen = data['kitchen'] self.tv = data['tv'] self.parking = data['parking'] self.elevator = data['elevator'] self.lat_coordinate = data['location'][0] self.long_coordinate = data['location'][1] self.address = data['address'] self.transport_info = data['transport_info'] self.persons_num = data['persons_number'] self.standard_cost = data['cost_per_day'] self.add_persons_cost = data['add_persons_cost'] self.title = data['title'] self.area = data['area'] self.min_stay = data['min_stay'] db.session.commit() """///////////////////////////////////////////////////////////"""