示例#1
0
class Transaction(db.Model):
    __tablename__ = "transaction"
    id = db.Column(db.Integer, unique=True, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)

    seats = db.relationship('Seat', backref='transaction', lazy=True)

    # Readonly list
    viewings = db.relationship('Viewing',
                               secondary='seat',
                               back_populates='transactions',
                               viewonly=True,
                               sync_backref=False)

    datetime = db.Column(db.DateTime, nullable=False, default=datetime.now())

    def get_cost(self):
        cost = 0.0
        for s in self.seats:
            cost += s.ticket_type.price
        return cost

    def get_receipt_path(self):
        return os.path.join(current_app.root_path, "bookings", "receipts",
                            str(self.id) + ".pdf")
示例#2
0
class Screen(db.Model):
    __tablename__ = "screen"
    id = db.Column(db.Integer, unique=True, primary_key=True)

    viewings = db.relationship('Viewing', backref='screen', lazy=True)

    name = db.Column(db.String(5), nullable=False, unique=True)
示例#3
0
class Movie(db.Model):
    __tablename__ = "movie"
    id = db.Column(db.Integer, unique=True, primary_key=True)
    viewings = db.relationship('Viewing', backref='movie', lazy=True)

    # Data fields
    # TODO Fix string lengths
    name = db.Column(db.String(100), nullable=False)
    overview = db.Column(db.String(500), nullable=False)
    released = db.Column(db.Date, nullable=False)
    trailer = db.Column(db.String(500), nullable=False)

    duration = db.Column(db.Integer, nullable=False)
    rating = db.Column(db.Float, nullable=False)
    hidden = db.Column(db.Boolean, nullable=False)

    cover_art_name = db.Column(db.String(35), nullable=False)

    # Should probably be own table cba
    directors = db.Column(db.String(250), nullable=True)
    cast = db.Column(db.String(250), nullable=True)
    genres = db.Column(db.String(250), nullable=True)

    def rel_cover_art_path(self):
        return 'cover_arts/' + self.cover_art_name

    def get_star_rating_html(self):
        # Full stars
        stars = '<i class="bi bi-star-fill mr-1"></i>' * floor(self.rating)
        # Half star
        if self.rating != floor(self.rating):
            stars += '<i class="bi bi-star-half mr-1"></i>'
        # Empty stars
        stars += '<i class="bi bi-star mr-1"></i>' * floor(5 - self.rating)
        return Markup(stars)
示例#4
0
class TicketType(db.Model):
    __tablename__ = 'ticket_type'
    id = db.Column(db.Integer, primary_key=True)

    seats = db.relationship('Seat', backref='ticket_type', lazy=True)

    name = db.Column(db.String(20), nullable=False, unique=True)
    price = db.Column(db.Float, nullable=False)
示例#5
0
class Role(db.Model):
    __tablename__ = 'role'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), nullable=False, unique=True)

    users = db.relationship('User',
                            secondary='user_role',
                            back_populates='roles',
                            sync_backref=False)
示例#6
0
class User(db.Model, UserMixin):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True)

    transactions = db.relationship('Transaction', backref='user', lazy=True)
    saved_cards = db.relationship('SavedCard', backref='user', lazy=True)

    # Readonly list
    roles = db.relationship('Role',
                            secondary='user_role',
                            back_populates='users',
                            viewonly=True)

    # Data fields
    email = db.Column(db.String(320), nullable=False, unique=True)
    first_name = db.Column(db.String(20), nullable=False)
    last_name = db.Column(db.String(20), nullable=False)
    username = db.Column(db.String(20), unique=True, nullable=False)
    password_hash = db.Column(db.String(60), nullable=False)
    confirmed = db.Column(db.Boolean, nullable=False, default=False)

    created = db.Column(db.DateTime, nullable=False, default=datetime.now())
    last_login = db.Column(db.DateTime, nullable=True)

    def get_reset_password_token(self, expires_in=86400):
        return jwt.encode(payload={
            'reset_password': self.id,
            'exp': time() + expires_in
        },
                          key=app.config['SECRET_KEY'],
                          algorithm='HS256')

    @staticmethod
    def verify_reset_password_token(token):
        try:
            id = jwt.decode(token,
                            app.config['SECRET_KEY'],
                            algorithms=['HS256'])['reset_password']
        except jwt.ExpiredSignatureError:
            return
        except jwt.DecodeError:
            return
        except jwt.InvalidTokenError:
            return
        return User.query.get(id)

    def get_email_confirm_token(self, expires_in=86400):
        return jwt.encode(payload={
            'email_confirm': self.id,
            'exp': time() + expires_in
        },
                          key=app.config['SECRET_KEY'],
                          algorithm='HS256')

    @staticmethod
    def verify_email_confirm_token(token):
        try:
            user_id = jwt.decode(token,
                                 app.config['SECRET_KEY'],
                                 algorithms=['HS256'])['email_confirm']
        except jwt.ExpiredSignatureError:
            return
        except jwt.DecodeError:
            return
        except jwt.InvalidTokenError:
            return
        return User.query.get(user_id)

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

    def set_password(self, password):
        self.password_hash = bcrypt.generate_password_hash(password).decode(
            'utf-8')
示例#7
0
class Viewing(db.Model):
    __tablename__ = "viewing"
    id = db.Column(db.Integer, unique=True, primary_key=True)
    movie_id = db.Column(db.Integer, db.ForeignKey('movie.id'), nullable=False)
    screen_id = db.Column(db.Integer,
                          db.ForeignKey('screen.id'),
                          nullable=False)

    seats = db.relationship('Seat', backref='viewing', lazy=True)

    # Readonly list
    transactions = db.relationship('Transaction',
                                   secondary='seat',
                                   back_populates='viewings',
                                   viewonly=True,
                                   sync_backref=False)

    # TODO Rename to datetime?
    time = db.Column(db.DateTime, nullable=False)

    def is_seat_available(self, seat_number):
        s = Seat.query.filter_by(viewing_id=self.id,
                                 seat_number=seat_number,
                                 transaction_id=None).first()
        return s is not None

    def init_seats(self):
        for char in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']:
            for i in range(1, 10):
                self.seats.append(Seat(seat_number=char + str(i)))
        db.session.commit()

    def book_seats(self, seats, user: User) -> (Transaction, str):
        """
        Books seats for the given user
        @param seats: List of tuples (seat num, ticket type) [('A1', 'Child'), ('A2', 'Adult')]
        @param user: User to book tickets for
        @return: New transaction object, Success / error message
        """
        if len(seats) == 0:
            return None, 'Missing seats'

        new_transaction = Transaction(user_id=user.id)
        for seat_number, ticket_type in seats:
            # Check number is correct
            if not Seat.is_number_type_valid(seat_number, ticket_type):
                return None, f'Seat \'{seat_number}\' with type \'{ticket_type}\' is invalid'

            s = Seat.query.filter_by(viewing_id=self.id,
                                     seat_number=seat_number).first()
            if not s:
                return None, f'Seat \'{seat_number}\' not found'

            if s.transaction_id is not None:
                return None, f'Seat \'{seat_number}\' already booked'

            ticket_type = TicketType.query.filter_by(name=ticket_type).first()
            if not ticket_type:
                return None, f'Ticket type {ticket_type} not found'

            new_transaction.seats.append(s)
            ticket_type.seats.append(s)

        db.session.commit()
        return new_transaction, 'Seats booked successfully'