1. View, filter, and save Product Permutation. \n 2. Synchronised with Product Category page and all common functionality moved into base and base table css, js, and python files.

This commit is contained in:
2024-09-24 23:25:52 +01:00
parent 2954b2050c
commit 45ac0405b4
243 changed files with 6596 additions and 4460 deletions

0
controllers/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

94
controllers/core.py Normal file
View File

@@ -0,0 +1,94 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Core Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# IMPORTS
# internal
from datastores.datastore_base import DataStore_Base
from forms.forms import Form_Contact
from models.model_view_admin_home import Model_View_Admin_Home
from models.model_view_contact import Model_View_Contact
from models.model_view_home import Model_View_Home
from models.model_view_services import Model_View_Services
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from flask_mail import Mail, Message
from extensions import db, oauth, mail
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_core = Blueprint('routes_core', __name__)
@routes_core.route(Model_View_Home.HASH_PAGE_HOME, methods=['GET'])
def home():
try:
model = Model_View_Home()
print('nips')
html_body = render_template('pages/core/_home.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
@routes_core.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['GET'])
def contact():
try:
user = DataStore_Base.get_user_session()
form = Form_Contact()
form.email.data = user.email
form.name.data = user.firstname + (' ' if user.firstname and user.surname else '') + user.surname
model = Model_View_Contact(form)
html_body = render_template('pages/core/_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
@routes_core.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['POST'])
def contact_post():
try:
form = Form_Contact()
if form.validate_on_submit():
# Handle form submission
email = form.email.data
CC = form.CC.data # not in use
name = form.name.data
message = form.message.data
# send email
mailItem = Message("PARTS Website Contact Us Message", recipients=[current_app.config['MAIL_CONTACT_PUBLIC']])
mailItem.body = f"Dear Lord Edward Middleton-Smith,\n\n{message}\n\nKind regards,\n{name}\n{email}"
mail.send(mailItem)
return "Submitted."
return "Invalid. Failed to submit."
# html_body = render_template('pages/core/_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
@routes_core.route(Model_View_Services.HASH_PAGE_SERVICES, methods=['GET', 'POST'])
def services():
try:
model = Model_View_Services()
html_body = render_template('pages/core/_services.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
@routes_core.route(Model_View_Admin_Home.HASH_PAGE_ADMIN_HOME, methods=['GET', 'POST'])
def admin_home():
try:
model = Model_View_Admin_Home()
html_body = render_template('pages/core/_admin_home.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body

74
controllers/legal.py Normal file
View File

@@ -0,0 +1,74 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Legal Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# IMPORTS
# internal
# from models.model_view_home import Model_View_Home
from models.model_view_license import Model_View_License
from models.model_view_privacy_policy import Model_View_Privacy_Policy
from models.model_view_accessibility_report import Model_View_Accessibility_Report
from models.model_view_accessibility_statement import Model_View_Accessibility_Statement
from models.model_view_retention_schedule import Model_View_Retention_Schedule
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_legal = Blueprint('routes_legal', __name__)
# snore
@routes_legal.route('/license', methods=['GET'])
def license():
try:
model = Model_View_License()
html_body = render_template('pages/legal/_license.html', model = model)
except Exception as e:
return str(e)
return html_body
@routes_legal.route('/accessibility-statement', methods=['GET'])
def accessibility_statement():
try:
model = Model_View_Accessibility_Statement()
html_body = render_template('pages/legal/_accessibility_statement.html', model = model)
except Exception as e:
return str(e)
return html_body
@routes_legal.route('/accessibility-report', methods=['GET'])
def accessibility_report():
try:
model = Model_View_Accessibility_Report()
html_body = render_template('pages/legal/_accessibility_report.html', model = model)
except Exception as e:
return str(e)
return html_body
@routes_legal.route('/retention-schedule', methods=['GET'])
def retention_schedule():
try:
model = Model_View_Retention_Schedule()
html_body = render_template('pages/legal/_retention_schedule.html', model = model)
except Exception as e:
return str(e)
return html_body
@routes_legal.route('/privacy-policy', methods=['GET'])
def privacy_policy():
try:
model = Model_View_Privacy_Policy()
html_body = render_template('pages/legal/_privacy_policy.html', model = model)
except Exception as e:
return str(e)
return html_body

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,99 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Store Product Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# internal
from business_objects.store.product import Product, Filters_Product
from forms.store.product import Form_Filters_Product
from models.model_view_store_product import Model_View_Store_Product
from helpers.helper_app import Helper_App
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_store_product = Blueprint('routes_store_product', __name__)
@routes_store_product.route(Model_View_Store_Product.HASH_PAGE_STORE_PRODUCTS, methods=['GET'])
def products():
print('products')
print(f'request.args={request.args}')
filters = Filters_Product.get_default()
have_changed_filters = False
arg_filter_is_not_empty = request.args.get(Model_View_Store_Product.FLAG_IS_NOT_EMPTY, None)
have_changed_filters = have_changed_filters or arg_filter_is_not_empty is None
print(f'arg_filter_is_not_empty={arg_filter_is_not_empty}')
filters.is_not_empty = filters.is_not_empty if arg_filter_is_not_empty is None else av.input_bool(arg_filter_is_not_empty, 'is_not_empty', 'filter')
arg_filter_active = request.args.get(Model_View_Store_Product.FLAG_ACTIVE, None)
have_changed_filters = have_changed_filters or arg_filter_active is None
print(f'arg_filter_active={arg_filter_active}')
filters.active = filters.active if arg_filter_active is None else av.input_bool(arg_filter_active, 'active', 'filter')
if have_changed_filters:
print('redirecting')
return redirect(url_for('routes_store_product.products', **filters.to_json()))
model = Model_View_Store_Product(filters)
return render_template('pages/store/_products.html', model = model)
@routes_store_product.route(Model_View_Store_Product.HASH_GET_STORE_PRODUCT, methods=['POST'])
def filter():
data = Helper_App.get_request_data(request)
# form_filters = None
try:
form_filters = get_Form_Filters_Product(data)
if not form_filters.validate_on_submit():
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'})
# ToDo: manually validate category, product
filters_form = Filters_Product.from_form_filters_product(form_filters)
model = Model_View_Store_Product(filters = filters_form)
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model.category_list.to_json()})
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})
def get_Form_Filters_Product(data_request):
data_form = data_request[Model_View_Store_Product.KEY_FORM]
form_filters = Form_Filters_Product(**data_form)
form_filters.is_not_empty.data = av.input_bool(data_form['is_not_empty'], 'is_not_empty', 'filter')
form_filters.active.data = av.input_bool(data_form['active'], 'active', 'filter')
return form_filters
@routes_store_product.route(Model_View_Store_Product.HASH_SAVE_STORE_PRODUCT, methods=['POST'])
def save():
data = Helper_App.get_request_data(request)
# form_filters = None
print(f'data={data}')
try:
form_filters = get_Form_Filters_Product(data)
if not form_filters.validate_on_submit():
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'})
filters_form = Filters_Product.from_form(form_filters)
categories = data[Model_View_Store_Product.FLAG_PRODUCT]
if len(categories) == 0:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'No categories.'})
objsCategory = []
for category in categories:
objsCategory.append(Product.from_json(category))
# model_save = Model_View_Store_Product() # filters_product=filters_form)
print(f'objsCategory={objsCategory}')
Model_View_Store_Product.save_categories(data.get('comment', 'No comment'), objsCategory)
model_return = Model_View_Store_Product(filters=filters_form)
print('nips')
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model_return.category_list.to_json()})
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})

View File

@@ -0,0 +1,119 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Store Product Category Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# internal
from business_objects.store.product_category import Product_Category #, Filters_Product_Category
from forms.store.product_category import Filters_Product_Category
from models.model_view_store_product_category import Model_View_Store_Product_Category
from helpers.helper_app import Helper_App
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_store_product_category = Blueprint('routes_store_product_category', __name__)
@routes_store_product_category.route(Model_View_Store_Product_Category.HASH_PAGE_STORE_PRODUCT_CATEGORIES, methods=['GET'])
def categories():
print('categories')
# data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Product_Category.from_json(request.args)
except Exception as e:
print(f'Error: {e}')
form_filters = Filters_Product_Category()
print(f'form_filters={form_filters}')
"""
filters = Filters_Product_Category.get_default()
have_changed_filters = False
arg_filter_is_not_empty = request.args.get(Model_View_Store_Product_Category.FLAG_IS_NOT_EMPTY, None)
have_changed_filters = have_changed_filters or arg_filter_is_not_empty is None
print(f'arg_filter_is_not_empty={arg_filter_is_not_empty}')
filters.is_not_empty = filters.is_not_empty if arg_filter_is_not_empty is None else av.input_bool(arg_filter_is_not_empty, 'is_not_empty', 'filter_category')
arg_filter_active = request.args.get(Model_View_Store_Product_Category.FLAG_ACTIVE, None)
have_changed_filters = have_changed_filters or arg_filter_active is None
print(f'arg_filter_active={arg_filter_active}')
filters.active = filters.active if arg_filter_active is None else av.input_bool(arg_filter_active, 'active', 'filter_category')
if have_changed_filters:
print('redirecting')
return redirect(url_for('routes_store_product_category.categories', **filters.to_json()))
"""
model = Model_View_Store_Product_Category(form_filters)
return render_template('pages/store/_product_categories.html', model = model)
@routes_store_product_category.route(Model_View_Store_Product_Category.HASH_GET_STORE_PRODUCT_CATEGORY, methods=['POST'])
def filter_category():
data = Helper_App.get_request_data(request)
# form_filters = None
try:
form_filters = Filters_Product_Category.from_json(data)
if not form_filters.validate_on_submit():
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE,
Model_View_Store_Product_Category.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'
})
# ToDo: manually validate category, product
# filters_form = Filters_Product_Category.from_form(form_filters)
model = Model_View_Store_Product_Category(form_filters = form_filters)
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS,
Model_View_Store_Product_Category.KEY_DATA: model.category_list.to_json()
})
except Exception as e:
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE,
Model_View_Store_Product_Category.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'
})
@routes_store_product_category.route(Model_View_Store_Product_Category.HASH_SAVE_STORE_PRODUCT_CATEGORY, methods=['POST'])
def save_category():
data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Product_Category.from_json(data[Model_View_Store_Product_Category.FLAG_FORM_FILTERS])
if not form_filters.validate_on_submit():
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE,
Model_View_Store_Product_Category.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'
})
# filters_form = Filters_Product_Category.from_form(form_filters)
categories = data[Model_View_Store_Product_Category.FLAG_PRODUCT_CATEGORY]
if len(categories) == 0:
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE,
Model_View_Store_Product_Category.FLAG_MESSAGE: f'No categories.'
})
objsCategory = []
for category in categories:
objsCategory.append(Product_Category.from_json(category))
# model_save = Model_View_Store_Product_Category() # filters_product=filters_form)
print(f'objsCategory={objsCategory}')
Model_View_Store_Product_Category.save_categories(data.get('comment', 'No comment'), objsCategory)
model_return = Model_View_Store_Product_Category(form_filters=form_filters)
print('nips')
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS,
Model_View_Store_Product_Category.KEY_DATA: model_return.category_list.to_json()
})
except Exception as e:
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE,
Model_View_Store_Product_Category.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'
})

View File

@@ -0,0 +1,159 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Store Product Permutation Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# internal
from business_objects.store.product import Filters_Product, Product_Permutation
from forms.store.product_permutation import Filters_Product_Permutation
from models.model_view_base import Model_View_Base
from models.model_view_store import Model_View_Store
from models.model_view_store_product_permutation import Model_View_Store_Product_Permutation
from helpers.helper_app import Helper_App
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_store_product_permutation = Blueprint('routes_store_product_permutation', __name__)
"""
@routes_store_product_permutation.route('/store/permutations', methods=['GET'])
def permutation():
filters = Filters_Product.get_default()
model = Model_View_Store_Product_Permutation(filters_product=filters)
return render_template('pages/store/_product_permutations.html', model = model)
@routes_store_product_permutation.route('/store/permutation_filter', methods=['POST'])
def permutation_filter():
data = Helper_App.get_request_data(request)
form_filters = None
try:
form_filters = get_Form_Filters_Permutation(data)
if not form_filters.validate_on_submit():
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'})
# ToDo: manually validate category, product
filters_form = Filters_Product.from_form(form_filters)
model = Model_View_Store_Product_Permutation(filters_product=filters_form)
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model.category_list.to_permutation_row_list()})
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})
def get_Form_Filters_Permutation(data_request):
data_form = data_request[Model_View_Store_Product_Permutation.KEY_FORM]
form_filters = Filters_Product_Permutation(**data_form)
form_filters.is_out_of_stock.data = av.input_bool(data_form['is_out_of_stock'], 'is_out_of_stock', 'permutations_post')
return form_filters
@routes_store_product_permutation.route('/store/permutation_save', methods=['POST'])
def permutation_save():
data = Helper_App.get_request_data(request)
form_filters = None
try:
form_filters = get_Form_Filters_Permutation(data)
if not form_filters.validate_on_submit():
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'})
permutations = data[Model_View_Store_Product_Permutation.FLAG_PRODUCT_PERMUTATION]
if len(permutations) == 0:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'No permutations.'})
objsPermutation = []
for permutation in permutations:
objsPermutation.append(Product_Permutation.from_json(permutation))
# ToDo: manually validate category, product
filters_form = Filters_Product.from_form(form_filters)
model_save = Model_View_Store_Product_Permutation(filters_product=filters_form)
model_save.save_permutations(data.comment, objsPermutation)
model_return = Model_View_Store_Product_Permutation(filters_product=filters_form)
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model_return.category_list.to_permutation_row_list()})
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})
"""
@routes_store_product_permutation.route(Model_View_Store_Product_Permutation.HASH_PAGE_STORE_PRODUCT_PERMUTATIONS, methods=['GET'])
def permutations():
print('permutations')
try:
form_filters = Filters_Product_Permutation.from_json(request.args)
except Exception as e:
print(f'Error: {e}')
form_filters = Filters_Product_Permutation()
print(f'form_filters={form_filters}')
model = Model_View_Store_Product_Permutation(form_filters)
return render_template('pages/store/_product_permutations.html', model = model)
@routes_store_product_permutation.route(Model_View_Store_Product_Permutation.HASH_GET_STORE_PRODUCT_PERMUTATION, methods=['POST'])
def filter_permutation():
data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Product_Permutation.from_json(data)
if not form_filters.validate_on_submit():
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE,
Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'
})
model = Model_View_Store_Product_Permutation(form_filters = form_filters)
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_SUCCESS,
Model_View_Store_Product_Permutation.KEY_DATA: model.category_list.to_json()
})
except Exception as e:
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE,
Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'
})
@routes_store_product_permutation.route(Model_View_Store_Product_Permutation.HASH_SAVE_STORE_PRODUCT_PERMUTATION, methods=['POST'])
def save_permutation():
data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Product_Permutation.from_json(data[Model_View_Store_Product_Permutation.FLAG_FORM_FILTERS])
if not form_filters.validate_on_submit():
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE,
Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'
})
# filters_form = Filters_Product_Permutation.from_form(form_filters)
print(f'form_filters: {form_filters}')
permutations = data[Model_View_Store_Product_Permutation.FLAG_PRODUCT_PERMUTATION]
if len(permutations) == 0:
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE,
Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'No permutations.'
})
objsPermutation = []
for permutation in permutations:
objsPermutation.append(Product_Permutation.from_json(permutation))
# model_save = Model_View_Store_Product_Permutation() # filters_product=filters_form)
print(f'objsPermutation={objsPermutation}')
Model_View_Store_Product_Permutation.save_permutations(data.get('comment', 'No comment'), objsPermutation)
model_return = Model_View_Store_Product_Permutation(form_filters=form_filters)
print('nips')
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_SUCCESS,
Model_View_Store_Product_Permutation.KEY_DATA: model_return.category_list.to_json()
})
except Exception as e:
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE,
Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'
})

View File

@@ -0,0 +1,92 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Store Stock Item Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# internal
from business_objects.store.product import Product, Filters_Product, Product_Permutation
from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters
from forms.forms import Form_Filters_Stock_Item
from models.model_view_base import Model_View_Base
from models.model_view_store import Model_View_Store
from models.model_view_store_supplier import Model_View_Store_Supplier
from models.model_view_store_product_category import Model_View_Store_Product_Category
from models.model_view_store_product_permutation import Model_View_Store_Product_Permutation
from models.model_view_store_stock_items import Model_View_Store_Stock_Items
from helpers.helper_app import Helper_App
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_store_stock_item = Blueprint('routes_store_stock_item', __name__)
@routes_store_stock_item.route('/store/stock_items', methods=['GET'])
def stock():
filters = Stock_Item_Filters.get_default()
model = Model_View_Store_Stock_Items(filters_stock_item=filters)
return render_template('pages/store/_stock_items.html', model = model)
@routes_store_stock_item.route('/store/stock_item_filter', methods=['POST'])
def stock_filter():
data = Helper_App.get_request_data(request)
form_filters = None
try:
form_filters = get_form_filters_stock_items(data)
if not form_filters.validate_on_submit():
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'})
# ToDo: manually validate category, product
filters_form = Stock_Item_Filters.from_form(form_filters)
model = Model_View_Store_Stock_Items(filters_stock_item=filters_form)
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model.category_list.to_permutation_row_list()})
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})
def get_form_filters_stock_items(data_request):
data_form = data_request[Model_View_Store_Stock_Items.KEY_FORM]
form_filters = Form_Filters_Stock_Item(**data_form)
form_filters.is_out_of_stock.data = av.input_bool(data_form['is_out_of_stock'], 'is_out_of_stock', 'permutations_post')
return form_filters
@routes_store_stock_item.route('/store/stock_item_save', methods=['POST'])
def stock_save():
data = Helper_App.get_request_data(request)
"""
form_filters = None
try:
form_filters = get_form_filters_stock_items(data)
if not form_filters.validate_on_submit():
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'})
stock_items = data[Model_View_Store_Stock.KEY_PERMUTATIONS]
print(f'stock_items: {stock_items}')
if len(stock_items) == 0:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'No stock items.'})
objsStockItem = []
for stock_item in stock_items:
objsStockItem.append(Product_Permutation.from_json(stock_item))
print(f'objsStockItem: {objsStockItem}')
# ToDo: manually validate category, product
filters_form = Stock_Filters.from_form(form_filters)
model_save = Model_View_Store_Stock(filters_product=filters_form)
model_save.save_stock_items(data.comment, objsPermutation)
model_return = Model_View_Store_Stock(filters_product=filters_form)
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model_return.category_list.to_permutation_row_list()})
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})
"""

View File

@@ -0,0 +1,30 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Store Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# IMPORTS
# internal
from models.model_view_store import Model_View_Store
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_store = Blueprint('routes_store', __name__)
@routes_store.route(Model_View_Store.HASH_SCRIPTS_SECTION_STORE, methods=['GET'])
def scripts_section_store():
hash_page_current = request.args.get('hash_page_current', default = Model_View_Store.HASH_SCRIPTS_SECTION_STORE, type = str)
model = Model_View_Store(hash_page_current=hash_page_current)
return render_template('js/sections/store.js', model = model)

View File

@@ -0,0 +1,68 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Store Supplier Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# internal
from business_objects.store.product import Product, Filters_Product, Product_Permutation
from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters
from forms.forms import Form_Supplier, Form_Filters_Stock_Item
from models.model_view_base import Model_View_Base
from models.model_view_store import Model_View_Store
from models.model_view_store_supplier import Model_View_Store_Supplier
from models.model_view_store_product_category import Model_View_Store_Product_Category
from models.model_view_store_product_permutation import Model_View_Store_Product_Permutation
from models.model_view_store_stock_items import Model_View_Store_Stock_Items
from helpers.helper_app import Helper_App
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_store_supplier= Blueprint('routes_store_supplier', __name__)
@routes_store_supplier.route('/supplier', methods=['GET'])
def supplier():
try:
data = request.json
except:
data = {}
print(f'data={data}')
form_data = data[Model_View_Store_Supplier.key_form]
print(f'form_data: {form_data}')
form = Form_Supplier(**form_data)
print('form acquired')
print(form.__repr__)
if form.validate_on_submit():
print('valid form')
# model = input_JSON_basket(model, data)
# if not logged in:
try:
model = Model_View_Store_Supplier(form)
# print('importing basket')
# model.import_JSON_basket(data)
model.get_basket(data)
permutation_id, quantity = model.import_JSON_basket_item(data, form)
model.basket_item_edit(permutation_id, quantity, False) # new_basket =
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})
# return jsonify(Success = True, data = { html_block: render_template(), Model_View_Store.key_basket: new_basket })
# html_block = render_template('_block_store_basket.html', model = model)
# print(f'html_block:\n{html_block}')
# return jsonify(Success = True, data = { 'html_block': html_block, 'basket': {'items': model.basket.to_json_list()}})
return render_template('pages/store/_supplier.html', model = model)
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Invalid supplier details.\n{form.errors}'})

169
controllers/user.py Normal file
View File

@@ -0,0 +1,169 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: User Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# IMPORTS
# internal
from models.model_view_base import Model_View_Base
from models.model_view_user import Model_View_User
from business_objects.user import User, User_Filters
from datastores.datastore_user import DataStore_User
from helpers.helper_app import Helper_App
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_user = Blueprint('routes_user', __name__)
# User authentication
@routes_user.route("/login", methods=['POST'])
def login():
try:
data = request.json
except:
data = {}
print(f'data={data}')
# callback_login = F'{Model_View_Base.HASH_CALLBACK_LOGIN}{data.get(Model_View_Base.KEY_CALLBACK, Model_View_Base.HASH_PAGE_HOME)}'
# encoded_path = quote(data.get(Model_View_Base.KEY_CALLBACK, Model_View_Base.HASH_PAGE_HOME))
uri_redirect = url_for('routes_user.login_callback', _external=True) # , subpath=encoded_path
# uri_redirect = f'{current_app.URL_HOST}/login_callback?subpath={data.get(Model_View_Base.KEY_CALLBACK, Model_View_Base.HASH_PAGE_HOME)}'
print(f'redirect uri: {uri_redirect}')
hash_callback = data.get(Model_View_Base.KEY_CALLBACK, Model_View_Base.HASH_PAGE_HOME)
print(f'hash_callback: {hash_callback}')
red = oauth.auth0.authorize_redirect(
redirect_uri = uri_redirect,
state = quote(hash_callback)
)
print(f'redirect: {red}')
headers = red.headers['Location']
print(f'headers: {headers}')
parsed_url = urlparse(headers)
query_params = parse_qs(parsed_url.query)
print(f"""
OAuth Authorize Redirect URL:
Base URL: {parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path}
{parsed_url}
Query Parameters: {query_params}
""")
return jsonify({'Success': True, Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, f'{Model_View_Base.KEY_CALLBACK}': headers})
@routes_user.route("/login_callback") # <path:subpath>/<code>
def login_callback():
try:
# print(f'code: {code}')
token = None
try:
token = oauth.auth0.authorize_access_token()
except Exception as e:
# Log the error for debugging
print(f"Error: {str(e)}")
session[current_app.config['ID_TOKEN_USER']] = token
# import user id
print(f'str(type(token)) = {str(type(token))}')
print(f'token = {token}')
userinfo = token.get('userinfo')
print(f'user info: {userinfo}')
# id_user = token.get('sub')
id_user = userinfo.get('sub')
print(f'user ID: {id_user}')
datastore_user = DataStore_User()
user = datastore_user.get_user_auth0()
user_filters = User_Filters.from_user(user)
users, errors = datastore_user.get_many_user(user_filters, user)
try:
user = users[0]
print('User logged in')
print(f'user ({str(type(user))}): {user}')
print(f'user key: {Model_View_Base.KEY_USER}')
user_json = user.to_json()
session[Model_View_Base.KEY_USER] = user_json
print(f'user stored on session')
except:
print(f'User not found: {user_filters}\nDatabase query error: {errors}')
try:
hash_callback = token.get('hash_callback')
if hash_callback is None:
print('hash is none')
state = request.args.get('state')
print(f'state: {state}')
hash_callback = state # .get('hash_callback')
print(f'hash_callback: {hash_callback}')
except:
print("get hash callback failed")
# id_user = get_id_user()
# add user to database
# DataStore_Store().add_new_user(id_user) # this is part of get basket - should occur on page load
print(f'user session: {session[Model_View_Base.KEY_USER]}')
return redirect(f"{current_app.config['URL_HOST']}{hash_callback}")
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Controller error.\n{e}'})
@routes_user.route("/logout")
def logout():
session.clear()
url_logout = f"https://{current_app.config['DOMAIN_AUTH0']}/v2/logout?" + urlencode(
{
"returnTo": url_for("routes_user.logout_callback", _external=True),
"client_id": current_app.config['ID_AUTH0_CLIENT'],
}# ,
# quote_via=quote_plus,
)
current_app.logger.debug(f"Redirecting to {url_logout}")
print(f"Redirecting to {url_logout}")
return redirect(url_logout)
@routes_user.route("/logout_callback") # <path:subpath>/<code>
def logout_callback():
return redirect(url_for('routes_core.home'))
try:
session[current_app.ID_TOKEN_USER] = None
user = User()
try:
hash_callback = token.get('hash_callback')
if hash_callback is None:
print('hash is none')
state = request.args.get('state')
print(f'state: {state}')
hash_callback = state # .get('hash_callback')
print(f'hash_callback: {hash_callback}')
except:
print("get hash callback failed")
# id_user = get_id_user()
# add user to database
# DataStore_Store().add_new_user(id_user) # this is part of get basket - should occur on page load
print(f'user session: {session[Model_View_Base.KEY_USER]}')
return redirect(f'{current_app.URL_HOST}{hash_callback}')
except Exception as e:
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Controller error.\n{e}'})
@routes_user.route("/user")
def user():
try:
model = Model_View_User(current_app, db)
html_body = render_template('pages/user/_user.html', model = model)
except Exception as e:
return str(e)
return html_body