WMGZON/controllers/web/product.py

244 lines
7.3 KiB
Python

"""
Product related endpoints. Included contexts for principles such as
categories and image processing.
"""
from flask import (
render_template, session, flash, request, redirect, Blueprint, url_for
)
from models.products.product import Product
from models.stats import Stats
from controllers.database.product import ProductController
from controllers.database.category import CategoryController
from controllers.database.stats import StatsController
from datetime import datetime
from utils.file_utils import save_image, remove_file
from utils.user_utils import is_role
import os
blueprint = Blueprint("products", __name__, url_prefix="/products")
# List of available filters for the user to select
FILTERS = {
# ANY INFOMRATION PUT INTO THE VALUES HERE WILL BE INTERPRETED AS SQL!!!
'Relevance': 'ORDER BY quantityAvailable DESC',
'Price: High -> Low': 'ORDER BY cost DESC',
'Price: Low -> High': 'ORDER BY cost'
}
@blueprint.context_processor
def filter_list():
""" Places a list of all the available filters in the
products context
"""
return dict(filters=FILTERS)
def get_filter():
""" Return any filters that are currently active on the page """
filter = request.args.get('filter')
if filter is None:
filter = 'Relevance'
if filter in FILTERS:
return FILTERS[filter]
return FILTERS['Relevance']
@blueprint.context_processor
def category_list():
""" Places a list of all categories in the products context """
database = CategoryController()
categories = database.read_all()
return dict(categories=categories)
@blueprint.route('/')
def index():
""" The front product page """
# Returning an empty category acts the same
# as a generic home page
return category("")
@blueprint.route('/<string:category>')
def category(category: str):
""" Loads a given categories page """
database = ProductController()
# Check to see if there is a custome search term
search_term = request.args.get("search", type=str)
if search_term is not None:
products = database.read_all(category, search_term, get_filter())
else:
products = database.read_all(category, "", get_filter())
# No Products visible
if products is None:
flash(
f"No Products available. Try expanding your search criteria.",
"warning"
)
return render_template(
'index.html',
content="content.html",
products=products,
category=category
)
@blueprint.route('/<int:id>')
def product(id: int):
""" Loads a given product based on ID """
db = ProductController()
product = db.read_id(id)
# Check that a valid product was returned
if product is None:
flash(f"No Product available with id {id}", "warning")
return redirect(url_for('main.index'))
# Record a view on the product
db = StatsController()
user_id = session.get('user_id')
db.create(Stats(product.id, user_id))
return render_template(
'index.html',
content='product.html',
product=product
)
@blueprint.route('/add')
def display_add():
""" Launches the page to add a new product to the site """
# User needs to be logged in as a seller to view this page
if not is_role("Seller"):
flash("You must be logged in as a seller to view this page!", "error")
return redirect(url_for('main.index'))
return render_template('index.html', content='new_product.html')
@blueprint.post('/add')
def add():
""" Server site processing to handle a request to add a
new product to the site
"""
user_id = session.get('user_id')
# User needs to be logged in as a seller to view this page
if not is_role("Seller"):
flash("You must be logged in as a seller to view this page!", "error")
return redirect(url_for('main.index'))
file = request.files.get('image')
image_filename = save_image(file)
product = Product(
request.form.get('name'),
image_filename if image_filename is not None else "",
request.form.get('description'),
request.form.get('cost'),
request.form.get('category'),
user_id,
datetime.now(),
request.form.get('quantity')
)
db = ProductController()
db.create(product)
return redirect('/products/ownproducts')
@blueprint.post('/update/<int:id>')
def update(id: int):
""" Processes a request to update a product in place on the site """
# Ensure that the product belongs to the current user
user_id = session.get('user_id')
# User needs to be logged in as a seller to view this page
if not is_role("Seller"):
flash("You must be logged in as a seller to view this page!", "error")
return redirect(url_for('main.index'))
db = ProductController()
product = db.read_id(id)
if product.sellerID != user_id:
flash("This product does not belong to you!", "error")
return redirect(url_for('main.products.own'))
# Save new image file
file = request.files.get('image')
new_image = save_image(file)
if new_image is not None:
remove_file(os.path.join(os.environ.get('FILESTORE'), product.image))
product.image = new_image
# Update product details
product.name = request.form.get('name')
product.description = request.form.get('description')
product.category = request.form.get('category')
product.cost = request.form.get('cost')
product.quantityAvailable = request.form.get('quantity')
db.update(product)
flash("Product successfully updated", 'notice')
return redirect(url_for('main.products.product', id=product.id))
@blueprint.post('/delete/<int:id>')
def delete(id: int):
""" Processes a request to delete a product in place on the site """
# Ensure that the product belongs to the current user
user_id = session.get('user_id')
# User needs to be logged in as a seller to view this page
if not is_role("Seller"):
flash("You must be logged in as a seller to view this page!", "error")
return redirect(url_for('main.index'))
db = ProductController()
product = db.read_id(id)
if product.sellerID != user_id:
flash("This product does not belong to you!", "error")
return redirect(url_for('main.products.display_own'))
db.delete(id)
flash("Product Removed!", "success")
return redirect(url_for('main.products.display_own'))
@blueprint.route('/ownproducts')
def display_own():
""" Display products owned by the currently logged in seller """
user_id = session.get('user_id')
# User must be logged in as seller to view page
if not is_role("Seller"):
flash("You must be logged in as a seller to view this page!", "error")
return redirect(url_for('main.index'))
db = ProductController()
products = db.read_user(user_id)
if products is None:
flash("You don't currently have any products for sale.", "info")
return render_template(
'index.html',
content='content.html',
products=products
)