Exemple #1
0
class Code(db.Model):
    __tablename__ = CODE
    code_id = db.Column(db.Integer, primary_key=True)
    code = db.Column(db.String(8), nullable=False)
    active = db.Column(db.Boolean, nullable=False, default=True)
    user_id = db.Column(db.Integer, db.ForeignKey(f"{USERS}.user_id"))
    user = db.relationship('User', back_populates='code', single_parent=True)
    purchases = db.relationship('Purchase', back_populates='code')

    def __repr__(self):
        return self.code

    def promoter(self):
        if self.user is None:
            return "-"
        return self.user

    def deactivate(self):
        self.active = False
        self.user = None

    def qr_code(self):
        url = pyqrcode.create(
            url_for("main.index", code=self.code, _external=True))
        return url.png_as_base64_str(scale=10)
Exemple #2
0
class File(db.Model):
    __tablename__ = FILE
    file_id = db.Column(db.Integer, primary_key=True)
    path = db.Column(db.String(256), nullable=False)
    name = db.Column(db.String(256), nullable=False)
    type = db.Column(db.String(128), nullable=False)
    party_id = db.Column(db.Integer, db.ForeignKey(f"{PARTY}.party_id"))
    # party = db.relationship('Party', back_populates='files')
    parties = db.relationship("Party", secondary=party_file_table)

    def url(self):
        return"{static}{file}"\
            .format(static=current_app.static_url_path, file=self.path.split("static")[1].replace('\\', '/'))
Exemple #3
0
class Ticket(db.Model):
    __tablename__ = TICKET
    ticket_id = db.Column(db.Integer, primary_key=True)
    used = db.Column(db.Boolean, index=True, nullable=False, default=False)
    denied_entry = db.Column(db.Boolean,
                             index=True,
                             nullable=False,
                             default=False)
    number = db.Column(db.Integer, nullable=False, default=0)
    refunded = db.Column(db.Boolean, nullable=False, default=False)
    purchase_id = db.Column(db.Integer,
                            db.ForeignKey(f"{PURCHASE}.purchase_id"))
    purchase = db.relationship('Purchase',
                               back_populates='tickets',
                               single_parent=True)
Exemple #4
0
class Refund(db.Model):
    __tablename__ = REFUND
    refund_id = db.Column(db.Integer, primary_key=True)
    price = db.Column(db.Integer, nullable=False, default=0)
    refund_datetime = db.Column(db.DateTime, default=datetime.utcnow)
    purchase_id = db.Column(db.Integer,
                            db.ForeignKey(f"{PURCHASE}.purchase_id"))
    purchase = db.relationship('Purchase',
                               back_populates='refunds',
                               single_parent=True)
    mollie_refund_id = db.Column(db.String(128), nullable=False, default="")

    def set_price(self, price_float):
        self.price = int(price_float * 100)

    def get_price(self):
        return float(self.price) / 100

    def refund_json(self):
        return {
            "refund_id": self.refund_id,
            "price": self.get_price(),
            "mollie_refund_id": self.mollie_refund_id,
        }
Exemple #5
0
class User(UserMixin, Anonymous, db.Model):
    __tablename__ = USERS
    user_id = db.Column(db.Integer, primary_key=True)
    reset_index = db.Column(db.Integer, nullable=False, default=0)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(128), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    access = db.Column(db.Integer, index=True, nullable=False)
    is_active = db.Column(db.Boolean,
                          index=True,
                          nullable=False,
                          default=False)
    last_seen = db.Column(db.DateTime, default=datetime.utcnow)
    code = db.relationship('Code', back_populates='user', uselist=False)
    hostess_id = db.Column(db.Integer, db.ForeignKey('users.user_id'))
    hostesses = db.relationship("User",
                                backref=db.backref('club_owner',
                                                   remote_side=[user_id]))
    parties = db.relationship('Party', back_populates='club_owner')
    purchases = db.relationship('Purchase', back_populates='promoter')
    commission = db.Column(db.Integer, nullable=False, default=0)
    activation_code = db.Column(db.String(128))

    def __repr__(self):
        return f'{self.username}'

    def get_id(self):
        return f"{self.user_id}-{self.reset_index}"

    def is_admin(self):
        return self.access == ACCESS[ADMIN]

    def is_organizer(self):
        return self.access == ACCESS[ORGANIZER]

    def is_club_owner(self):
        return self.access == ACCESS[CLUB_OWNER]

    def is_promoter(self):
        return self.access == ACCESS[PROMOTER]

    def allowed(self, access_level):
        return self.access == access_level

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)
        if self.reset_index is not None:
            self.reset_index += 1
        db.session.commit()

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

    def get_reset_password_token(self, expires_in=600):
        return jwt.encode(
            {
                'reset_password': self.user_id,
                'exp': time() + expires_in
            },
            current_app.config['SECRET_KEY'],
            algorithm='HS256').decode('utf-8')

    @staticmethod
    def verify_reset_password_token(token):
        try:
            user_id = jwt.decode(token,
                                 current_app.config['SECRET_KEY'],
                                 algorithms=['HS256'])['reset_password']
        except jwt.exceptions.InvalidTokenError:
            return 'error'
        return User.query.get(user_id)
Exemple #6
0
class Purchase(db.Model):
    __tablename__ = PURCHASE
    purchase_id = db.Column(db.Integer, primary_key=True)
    price = db.Column(db.Integer, nullable=False, default=0)
    status = db.Column(db.String(128), nullable=False, default=STATUS_OPEN)
    name = db.Column(db.String(128), nullable=False)
    email = db.Column(db.String(128), index=True, nullable=False)
    hash = db.Column(db.String(160), nullable=False, default="")
    mollie_payment_id = db.Column(db.String(128), nullable=False, default="")
    purchase_datetime = db.Column(db.DateTime, default=datetime.utcnow())
    party_id = db.Column(db.Integer, db.ForeignKey(f"{PARTY}.party_id"))
    party = db.relationship('Party',
                            back_populates='purchases',
                            single_parent=True)
    tickets = db.relationship('Ticket',
                              back_populates='purchase',
                              cascade='all, delete-orphan')
    refunds = db.relationship('Refund',
                              back_populates='purchase',
                              cascade='all, delete-orphan')
    code_id = db.Column(db.Integer, db.ForeignKey(f"{CODE}.code_id"))
    code = db.relationship('Code', back_populates='purchases')
    promoter_id = db.Column(db.Integer, db.ForeignKey(f"{USERS}.user_id"))
    promoter = db.relationship('User', back_populates='purchases')
    promoter_commission = db.Column(db.Integer, nullable=False, default=15)
    club_owner_commission = db.Column(db.Integer, nullable=False, default=10)

    def __repr__(self):
        return f"Purchase {self.purchase_id} - Party: {self.party} - Tickets: {len(self.tickets)}"

    def set_price(self, price_float):
        self.price = int(price_float * 100)

    def get_price(self):
        return float(self.price) / 100

    def get_ticket_price(self):
        return self.get_price() / len(self.tickets)

    def mollie_description(self):
        return f"{len(self.tickets)} tickets to {self.party}"

    def mollie_price(self):
        return '{:,.2f}'.format(self.get_price())

    def set_hash(self):
        purchase_hash = self.calculate_hash()
        while Purchase.query.filter(
                Purchase.hash == purchase_hash).first() is not None:
            purchase_hash = self.calculate_hash(add_date=True)
        self.hash = purchase_hash
        return self.hash

    def calculate_hash(self, add_date=False):
        purchase_hash = f"Purchase {self.purchase_id} - Party: {self.party} - Email: {self.email} - " \
            f"{current_app.config.get('SECRET_KEY')}{datetime.utcnow() if add_date else ''}"
        return sha3_256(purchase_hash.encode()).hexdigest()

    def purchase_paid(self):
        self.status = STATUS_PAID

    def purchase_pending(self):
        self.status = STATUS_PENDING

    def cancel_purchase(self):
        self.status = STATUS_CANCELED

    def first_name(self):
        return self.name.split(" ")[0]

    def qr_code(self):
        url = pyqrcode.create(self.hash)
        return url.png_as_base64_str(scale=6)

    def entrance_code(self):
        return f"{ self.name }-{ self.purchase_id }".replace(" ", "")

    # PromoterFinances
    def promoter_tickets(self):
        return len(self.tickets)

    def promoter_price(self):
        return self.get_price() * self.promoter_commission / 100

    def refunded_tickets(self):
        return len([t for t in self.tickets if t.refunded])

    def refunded_price(self):
        return self.get_ticket_price() * self.refunded_tickets(
        ) * self.promoter_commission / 100

    def promoter_finances_json(self):
        return {
            "tickets": self.promoter_tickets(),
            "promoter_price": self.promoter_price(),
            "refunded_price": self.refunded_price()
        }

    # PastParties
    def get_price_with_refunds(self):
        return self.get_price() - self.purchase_refund()

    def purchase_refund(self):
        return sum([r.get_price() for r in self.refunds])

    def purchase_promoter_cut(self):
        return self.get_price_with_refunds() * self.promoter_commission / 100

    def purchase_club_owner_cut(self):
        return self.get_price_with_refunds() * self.club_owner_commission / 100

    def purchase_date(self):
        return self.purchase_datetime.strftime("%d-%m-%Y %H:%M")

    def refund_json(self):
        return {
            "purchase_id": self.purchase_id,
            "name": self.name,
            "email": self.email,
            "purchase_date": self.purchase_date(),
            "entrance_code": self.entrance_code(),
            "party_id": self.party.party_id,
            "party_title": self.party.title,
            "party_date": self.party.party_date(),
            "price": self.get_price(),
            "number_of_tickers": len(self.tickets),
            "refunds": [r.refund_json() for r in self.refunds],
            "status": self.status
        }
Exemple #7
0
class Party(db.Model):
    __tablename__ = PARTY
    party_id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(128), index=True, nullable=False)
    is_active = db.Column(db.Boolean,
                          index=True,
                          nullable=False,
                          default=False)
    party_start_datetime = db.Column(db.DateTime, default=datetime.utcnow())
    party_end_datetime = db.Column(db.DateTime,
                                   default=datetime.utcnow() +
                                   timedelta(hours=4))
    status = db.Column(db.String(128),
                       index=True,
                       nullable=False,
                       default=NORMAL)
    num_available_tickets = db.Column(db.Integer, nullable=False, default=0)
    ticket_price = db.Column(db.Integer, nullable=False, default=0)
    purchases = db.relationship('Purchase',
                                back_populates='party',
                                cascade='all, delete-orphan')
    club_owner_id = db.Column(db.Integer, db.ForeignKey(f"{USERS}.user_id"))
    club_owner = db.relationship('User', back_populates='parties')
    logo = db.Column(db.String(256), nullable=False)
    image = db.Column(db.String(256), nullable=False)
    # files = db.relationship('File', back_populates='party')
    files = db.relationship("File", secondary=party_file_table)
    club_owner_commission = db.Column(db.Integer, nullable=False, default=10)

    def __repr__(self):
        return f"{self.title}"

    def set_ticket_price(self, price_float):
        self.ticket_price = int(price_float * 100)

    def get_ticket_price(self):
        return float(self.ticket_price) / 100

    def tickets_with_status(self, status=""):
        return [
            t for p in self.purchases for t in p.tickets if p.status == status
        ]

    def num_tickets_with_status(self, status=""):
        return len(self.tickets_with_status(status))

    def sold_tickets(self):
        return self.num_tickets_with_status(STATUS_PAID)

    def tickets_on_hold(self):
        return self.num_tickets_with_status(
            STATUS_PENDING) + self.num_tickets_with_status(STATUS_OPEN)

    def remaining_tickets(self):
        return self.num_available_tickets - self.sold_tickets(
        ) - self.tickets_on_hold()

    def check_ticket_availability(self, requested_tickets):
        return self.remaining_tickets() >= requested_tickets

    def party_date(self):
        return self.party_start_datetime.strftime("%d %B, %Y")

    def party_time(self):
        return f'{self.party_start_datetime.strftime("%H:%M")} - {self.party_end_datetime.strftime("%H:%M")}'

    def json(self):
        return {
            "party_id": self.party_id,
            "title": self.title,
            "ticket_price": self.get_ticket_price(),
            'party_date': self.party_date(),
            'party_time': self.party_time()
        }

    def purchases_with_status(self, status=""):
        return [p for p in self.purchases if p.status == status]

    def paid_purchases(self):
        return self.purchases_with_status(STATUS_PAID)

    def party_potential_income(self):
        return sum([p.get_price() for p in self.paid_purchases()])

    def party_tickets_with_potential_refund(self):
        return [
            t for t in self.tickets_with_status(STATUS_PAID) if t.denied_entry
        ]

    def num_party_tickets_with_potential_refund(self):
        return len(self.party_tickets_with_potential_refund())

    def party_potential_refund(self):
        return sum([
            t.purchase.get_ticket_price()
            for t in self.party_tickets_with_potential_refund()
        ])

    def delete_files_from_hard_disk(self):
        self.image = PLACEHOLDER_URL
        self.logo = PLACEHOLDER_URL
        db.session.commit()
        for file in self.files:
            if os.path.isfile(file.path):
                os.remove(file.path)
            db.session.delete(file)
        db.session.commit()

    # PromoterFinances
    def promoter_finances_json(self):
        return {
            "party_id":
            self.party_id,
            "title":
            self.title,
            "party_date":
            self.party_date(),
            "tickets":
            sum([
                p.promoter_tickets() for p in self.purchases
                if p.promoter == current_user
            ]),
            "price":
            sum([
                p.promoter_price() for p in self.purchases
                if p.promoter == current_user
            ]),
            "refund_tickets":
            sum([
                p.refunded_tickets() for p in self.purchases
                if p.promoter == current_user
            ]),
            "refund_price":
            sum([
                p.refunded_price() for p in self.purchases
                if p.promoter == current_user
            ])
        }

    # PastParties
    def party_income(self):
        return sum([p.get_price() for p in self.purchases])

    def party_refunds(self):
        return sum([p.purchase_refund() for p in self.purchases])

    def party_promoter_cut(self):
        return sum([p.purchase_promoter_cut() for p in self.purchases])

    def party_club_owner_cut(self):
        return sum([p.purchase_club_owner_cut() for p in self.purchases])

    def party_profit(self):
        return self.party_income() - self.party_refunds(
        ) - self.party_promoter_cut() - self.party_club_owner_cut()

    def past_party_json(self):
        return {
            "party_id": self.party_id,
            "title": self.title,
            "party_date": self.party_date(),
            "party_time": self.party_time(),
            "num_available_tickets": self.num_available_tickets,
            "sold_tickets": self.sold_tickets(),
            "remaining_tickets": self.remaining_tickets(),
            "party_income": self.party_income(),
            "party_refunds": self.party_refunds(),
            "party_promoter_cut": self.party_promoter_cut(),
            "party_club_owner_cut": self.party_club_owner_cut(),
            "party_profit": self.party_profit()
        }
Exemple #8
0
                                              default=10)
    default_promoter_commission = db.Column(db.Integer,
                                            nullable=False,
                                            default=15)
    site_available = db.Column(db.Boolean, nullable=False, default=False)

    def allowed_file_types(self):
        return self.allowed_image_types.split(",")


party_file_table = db.Table(
    TABLE_PARTY_FILES, db.Model.metadata,
    db.Column(
        'party_id', db.Integer,
        db.ForeignKey(f'{PARTY}.party_id',
                      onupdate="CASCADE",
                      ondelete="CASCADE")),
    db.Column(
        'file_id', db.Integer,
        db.ForeignKey(f'{FILE}.file_id',
                      onupdate="CASCADE",
                      ondelete="CASCADE")),
    db.UniqueConstraint('party_id', 'file_id', name='_party_file_uc'))


class Party(db.Model):
    __tablename__ = PARTY
    party_id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(128), index=True, nullable=False)
    is_active = db.Column(db.Boolean,
                          index=True,