Source code for app.models

from datetime import datetime

from app import db, login
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash

UserRole = db.Table(
    'user_role', db.Model.metadata,
    db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('role_id', db.Integer, db.ForeignKey('role.id'))
)


[docs]class Role(db.Model): """ An Model object that contains the name of a role """ id = db.Column(db.Integer, primary_key=True) """The primary key of the role""" name = db.Column(db.String(255), nullable=False, unique=True) """The name of the role"""
[docs]class User(UserMixin, db.Model): """ A Model object that represents a user. Also supports UserMixin for FlaskLogin """ id = db.Column(db.Integer, primary_key=True) """The primary key of the user""" username = db.Column(db.String(64), unique=True) """The username of the user""" email = db.Column(db.String(64), unique=True) """The email of the user""" password_hash = db.Column(db.String(128)) """The hashed password of the user""" # relationships roles = db.relationship('Role', secondary='user_role', lazy='dynamic') """A queryable database relationship that retrieves the roles related to the user""" cart_items = db.relationship('CartItem', backref='user', lazy='dynamic') """A queryable relationship that retrieves the rows in the cart related to the customer user""" orders = db.relationship('Order', backref='user', lazy='dynamic') """A queryable relationship that retrieves the orders related to the customer user""" products = db.relationship('Product', backref='user', lazy='dynamic') """A queryable relationship that retrieves the products related to a merchant user"""
[docs] def set_password(self, password): """ Sets the password of the given User object :param str password: The new password to set """ self.password_hash = generate_password_hash(password)
[docs] def check_password(self, password): """ Checks a password input against the password stored in the User :param str password: The password to check :return: `True` if the passwords match, `False` if not :rtype: bool """ return check_password_hash(self.password_hash, password)
def __repr__(self): """ Returns a string representation of the User :return: A string in the format <User: username email> :rtype: str """ return f'<User: {self.username} {self.email}>'
[docs]class Category(db.Model): """ A Model object that represents a category of products """ id = db.Column(db.Integer, primary_key=True) """The primary key of the category""" name = db.Column(db.String(128)) """The name of the category""" products = db.relationship('Product', backref='category', lazy='dynamic') """A queryable relationship representing the products that belong to the category"""
[docs]class Product(db.Model): """ A Model object that represents a product """ id = db.Column(db.Integer, primary_key=True) """The primary key of the product""" category_id = db.Column(db.Integer, db.ForeignKey('category.id')) """The foreign key of the category the product belongs to""" merchant_id = db.Column(db.Integer, db.ForeignKey('user.id')) """The foreign key of the merchant User the product belongs to""" name = db.Column(db.String(128)) """The name of the product""" price = db.Column(db.Float) """The price of the product""" description = db.Column(db.Text) """The description of the product""" # Relationships reviews = db.relationship('Review', backref='product', lazy='dynamic') """A queryable database relationship that retrieves the reviews of the product""" images = db.relationship('Image', backref='product') """A instrumentedList that contains the Image objects related to the product""" orders = db.relationship("OrderRow", back_populates="product") """A relationship that retrieves orders of the product"""
[docs]class Image(db.Model): """ A Model object that contains information about an uploaded image """ id = db.Column(db.Integer, primary_key=True) """The primary key of the image""" product_id = db.Column(db.Integer, db.ForeignKey('product.id')) """The foreign key of which the image is related to""" path = db.Column(db.String(128)) """The path to the image"""
[docs]class CartItem(db.Model): """ A Model object that represents a row in a cart """ id = db.Column(db.Integer, primary_key=True) """The primary key of the cart item""" product_id = db.Column(db.Integer, db.ForeignKey('product.id')) """The foreign key that relates the row to a product""" user_id = db.Column(db.Integer, db.ForeignKey('user.id')) """The foreign key that relates the row to a customer user""" quantity = db.Column(db.Integer) """The quantity of the product ordered""" timestamp = db.Column(db.DateTime, default=datetime.utcnow) """The time at which the item was created""" def __repr__(self): return f'<User ID: {self.user_id} Item: >'
[docs]class Order(db.Model): """ A Model object that represents an order """ id = db.Column(db.Integer, primary_key=True) """The primary key of the order""" user_id = db.Column(db.Integer, db.ForeignKey('user.id')) """A foreign key that relates an order to a customer user""" ship_address = db.Column(db.String(128)) """The address that the order will be shipped to""" order_row = db.relationship('OrderRow', backref='order', lazy='dynamic') """A queryable relationship that retrieves the OrderRows belonging to an Order""" def __repr__(self): return f'id: {self.id}\n' \ f'user_id: {self.user_id}\n' \ f'ship_address: {self.ship_address}\n' \ f'order_row: {self.order_row}\n'
[docs]class OrderRow(db.Model): """ A Model object that represents a row of an Order """ row_id = db.Column(db.Integer, primary_key=True) """The primary key of the order row""" id = db.Column(db.Integer, db.ForeignKey('order.id')) """A foreign key that relates to the Order that the row belongs to""" product_id = db.Column(db.Integer, db.ForeignKey('product.id')) """A foreign key that relates to the product purchased in the row""" quantity = db.Column(db.Integer) """The number of the product that was purchased""" product_price = db.Column(db.Float) """The price of each product at the time it was purchased""" product = db.relationship("Product", back_populates="orders") """A relationship that links to the Product object purchased in the row""" filled = db.Column(db.Boolean, default=False) """A boolean that represents if the order was filled or not. Defaults to `False`.""" timestamp = db.Column(db.DateTime, default=datetime.utcnow) """The time at which the OrderRow was created. Defaults to `datetime.utcnow`.""" def __repr__(self): return f'row_id: {self.row_id}\n' \ f'order id: {self.id}\n' \ f'product_id: {self.product_id}\n' \ f'quantity: {self.quantity}\n' \ f'product_price: {self.product_price}\n'
[docs]class Review(db.Model): """ A Model object representing a review """ id = db.Column(db.Integer, primary_key=True) """The primary key of the review""" user_id = db.Column(db.Integer, db.ForeignKey('user.id')) """A foreign key that relates the review to a customer""" product_id = db.Column(db.Integer, db.ForeignKey('product.id')) """A foreign key that relates the review to a product""" rating = db.Column(db.Integer) """A numerical rating given in the review""" body = db.Column(db.Text) """The text body of the review""" timestamp = db.Column(db.DateTime, default=datetime.utcnow) """The time at which the review was written. Defaults to `datetime.utcnow`.""" def __repr__(self): username = User.query.filter_by(id=self.user_id).first().username return f'{username}\n' \ f'{self.rating}\n' \ f'{self.body}\n'
[docs]class Discount(db.Model): """ A Model object that represents a user. Also supports UserMixin for FlaskLogin. Construct a discount using the ``app.utils.create_discount`` method. """ id = db.Column(db.Integer, primary_key=True) """The primary key of the discount""" code = db.Column(db.String(64), nullable=False, unique=True) """The code of the discount that the user can use""" expiration = db.Column(db.DateTime) """The expiration date of the discount""" details = db.Column(db.JSON, nullable=False) """A JSON attribute containing the details of the discount"""
[docs] def is_valid(self): """ Compares the current datetime to the stored expiration date to confirm if the discount is still valid :return: `True` if the current date is on or before the expiration date. `False` if it is after. :rtype: bool """ cur_date = datetime.today() return cur_date <= self.expiration
[docs] def apply_discount(self, cart_item: int): """ Returns the discount amount for a given ``app.models.CartItem`` row id. :param cart_item: The id field of the ``app.models.CartItem`` :return: The discount amount for the given row. :rtype: float """ row = CartItem.query.get(cart_item) if self.is_valid() and row is not None: discount_details = self.details product = Product.query.get(row.product_id) if discount_details['type'] == 2: if discount_details['percentage']: discount = discount_details['amount'] * product.price return discount if not discount_details['percentage']: return discount_details['amount'] if discount_details['type'] == 1 and product.category_id in discount_details["applicable_id"]: if discount_details['percentage']: discount = discount_details['amount'] * product.price return discount if not discount_details['percentage']: return discount_details['amount'] if discount_details['type'] == 0 and product.id in discount_details["applicable_id"]: if discount_details['percentage']: discount = discount_details['amount'] * product.price return discount if not discount_details['percentage']: return discount_details['amount'] return 0 return 0
[docs]@login.user_loader def load_user(id): """ A user loader for flask login :param id: The ID of the user to retrieve :return: The User object that has the given ID :rtype: app.models.User """ return User.query.get(int(id))