diff --git a/app.py b/app.py index 57bd3e38..410246ac 100644 --- a/app.py +++ b/app.py @@ -17,25 +17,6 @@ Initializes the Flask application, sets the configuration based on the environme # IMPORTS # internal from config import app_config, Config -# from routes import bp_home -""" -from forms import Form_Contact, Form_Supplier, Form_Filters_Permutation, Filters_Stock_Item -from models.model_view_base import Model_View_Base -from models.model_view_admin import Model_View_Admin -from models.model_view_home import Model_View_Home -from models.model_view_contact import Model_View_Contact -from models.model_view_services import Model_View_Services -from models.Model_View_Store_Stock_Item import Model_View_Store_Stock_Item -from models.model_view_store_supplier import Model_View_Store_Supplier -from models.model_view_store_product_permutation import Model_View_Store_Product_Permutations -from models.model_view_user import Model_View_User -from business_objects.store.product import Product, Parameters_Product, Product_Permutation # , Product_Image_Filters, Resolution_Level_Enum -from business_objects.store.stock_item import Stock_Item -from business_objects.user import User, User_Filters -from datastores.datastore_store_base import DataStore_Store -from helpers.helper_app import Helper_App -import lib.argument_validation as av -""" from controllers.core import routes_core from controllers.legal import routes_legal from controllers.store.store import routes_store diff --git a/business_objects/__pycache__/unit_measurement.cpython-312.pyc b/business_objects/__pycache__/unit_measurement.cpython-312.pyc index 67f8f6df..aba33d16 100644 Binary files a/business_objects/__pycache__/unit_measurement.cpython-312.pyc and b/business_objects/__pycache__/unit_measurement.cpython-312.pyc differ diff --git a/business_objects/__pycache__/user.cpython-312.pyc b/business_objects/__pycache__/user.cpython-312.pyc index cca3d118..7c4484c7 100644 Binary files a/business_objects/__pycache__/user.cpython-312.pyc and b/business_objects/__pycache__/user.cpython-312.pyc differ diff --git a/business_objects/store/__pycache__/product.cpython-312.pyc b/business_objects/store/__pycache__/product.cpython-312.pyc index af8e7019..662673a7 100644 Binary files a/business_objects/store/__pycache__/product.cpython-312.pyc and b/business_objects/store/__pycache__/product.cpython-312.pyc differ diff --git a/business_objects/store/__pycache__/product_variation.cpython-312.pyc b/business_objects/store/__pycache__/product_variation.cpython-312.pyc index 860f529a..5244b8fa 100644 Binary files a/business_objects/store/__pycache__/product_variation.cpython-312.pyc and b/business_objects/store/__pycache__/product_variation.cpython-312.pyc differ diff --git a/business_objects/store/product.py b/business_objects/store/product.py index 880cffb8..2f06f41b 100644 --- a/business_objects/store/product.py +++ b/business_objects/store/product.py @@ -261,6 +261,7 @@ class Product(SQLAlchemy_ABC, Store_Base): has_variations: {self.has_variations} permutations: {self.permutations} variation trees: {self.variation_trees} + active: {self.active} ''' """ def get_index_permutation_from_id(self, id_permutation): diff --git a/business_objects/store/product_variation.py b/business_objects/store/product_variation.py index 20dacee0..e5ae26a8 100644 --- a/business_objects/store/product_variation.py +++ b/business_objects/store/product_variation.py @@ -118,69 +118,6 @@ class Product_Variation(db.Model, Store_Base): 'text': self.name } -""" -@dataclass -class Product_Variation_Filters(): - get_all_variation_type: bool - get_inactive_variation_type: bool - # get_first_variation_type: bool - ids_variation_type: str - get_all_variation: bool - get_inactive_variation: bool - # get_first_variation: bool - ids_variation: str - - def to_json(self): - return { - 'a_get_all_variation_type': self.get_all_variation_type, - 'a_get_inactive_variation_type': self.get_inactive_variation_type, - # 'a_get_first_variation_type': self.get_first_variation_type, - 'a_ids_variation_type': self.ids_variation_type, - 'a_get_all_variation': self.get_all_variation, - 'a_get_inactive_variation': self.get_inactive_variation, - # 'a_get_first_variation': self.get_first_variation, - 'a_ids_variation': self.ids_variation, - - } - "" - @staticmethod - def from_form(form): - av.val_instance(form, 'form', 'User_Filters.from_form', Filters_Product_Variation) - get_inactive = av.input_bool(form.active.data, "active", "User_Filters.from_form") - id_user = form.id_user.data - return User_Filters( - get_all_user = (id_user is None), - get_inactive_user = get_inactive, - get_first_user_only = False, - ids_user = id_user, - ids_user_auth0 = '', - ) - - @staticmethod - def from_user(user): - av.val_instance(user, 'user', 'User_Filters.from_user', User) - return User_Filters( - get_all_user = (user.id_user is None and user.id_user_auth0 is None), - get_inactive_user = False, - get_first_user_only = False, - ids_user = user.id_user, - ids_user_auth0 = user.id_user_auth0, - ) - "" - - @staticmethod - def get_default(): - return Product_Variation_Filters( - get_all_variation_type = True, - get_inactive_variation_type = False, - # get_first_variation_type = False, - ids_variation_type = '', - get_all_variation = True, - get_inactive_variation = False, - # get_first_variation = False, - ids_variation = '' - ) -""" class Parameters_Product_Variation(Get_Many_Parameters_Base): a_get_all_variation_type: bool a_get_inactive_variation_type: bool diff --git a/business_objects/unit_measurement.py b/business_objects/unit_measurement.py index a0b10b11..372026ff 100644 --- a/business_objects/unit_measurement.py +++ b/business_objects/unit_measurement.py @@ -108,54 +108,3 @@ class Unit_Measurement(SQLAlchemy_ABC, Base): is_unit_of_volume: {self.is_unit_of_volume}, active: {self.active} ''' - -""" -@dataclass -class Filters_Unit_Measurement(): - active_only: bool = False - - def to_json(self): - return { - **self.get_shared_json_attributes(self), - 'a_get_all_user': self.get_all_user, - 'a_get_inactive_user': self.get_inactive_user, - 'a_get_first_user_only': self.get_first_user_only, - 'a_ids_user': self.ids_user, - 'a_ids_user_auth0': self.ids_user_auth0, - } - - @staticmethod - def from_form(form): - av.val_instance(form, 'form', 'User_Filters.from_form', Form_Filters_User) - get_inactive = av.input_bool(form.active.data, "active", "User_Filters.from_form") - id_user = form.id_user.data - return User_Filters( - get_all_user = (id_user is None), - get_inactive_user = get_inactive, - get_first_user_only = False, - ids_user = id_user, - ids_user_auth0 = '', - ) - - @staticmethod - def from_user(user): - av.val_instance(user, 'user', 'User_Filters.from_user', User) - return User_Filters( - get_all_user = (user.id_user is None and user.id_user_auth0 is None), - get_inactive_user = False, - get_first_user_only = False, - ids_user = user.id_user, - ids_user_auth0 = user.id_user_auth0, - ) - - @staticmethod - def get_default(datastore_store): - user = datastore_store.get_login_user() - return User_Filters( - get_all_user = False, - get_inactive_user = False, - get_first_user_only = False, - ids_user = user.id_user, - ids_user_auth0 = '', - ) -""" \ No newline at end of file diff --git a/business_objects/user.py b/business_objects/user.py index 6364fda1..35f5c4c2 100644 --- a/business_objects/user.py +++ b/business_objects/user.py @@ -9,6 +9,7 @@ Feature: User Business Object # internal from business_objects.base import Base +from business_objects.db_base import Get_Many_Parameters_Base import lib.argument_validation as av from forms.forms import Form_Filters_User from extensions import db @@ -22,6 +23,9 @@ class User(db.Model, Base): NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_USER NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'email' + __tablename__ = 'Shop_User' + __table_args__ = { 'extend_existing': True } + id_user = db.Column(db.Integer, primary_key=True) id_user_auth0 = db.Column(db.String(255)) firstname = db.Column(db.String(255)) @@ -34,13 +38,16 @@ class User(db.Model, Base): is_included_VAT_default = db.Column(db.Boolean) can_admin_store = db.Column(db.Boolean) can_admin_user = db.Column(db.Boolean) - + is_new = db.Column(db.Boolean) # is_logged_in: bool def __init__(self): self.id_user = 0 self.is_logged_in = False + self.is_new = False super().__init__() + self.currency_default = None + self.region_default = None def from_DB_user(query_row): _m = 'User.from_DB_user' @@ -58,6 +65,7 @@ class User(db.Model, Base): user.can_admin_store = av.input_bool(query_row[10], 'can_admin_store', _m) user.can_admin_user = av.input_bool(query_row[11], 'can_admin_user', _m) user.is_logged_in = (user.id_user is not None and user.id_user > 0) + user.is_new = av.input_bool(query_row[12], 'is_new', _m) return user @staticmethod @@ -140,58 +148,42 @@ class User(db.Model, Base): can_admin_user: {self.can_admin_user} ''' - - -@dataclass -class User_Filters(): + +class Parameters_User(Get_Many_Parameters_Base): get_all_user: bool get_inactive_user: bool - get_first_user_only: bool ids_user: str ids_user_auth0: str - def to_json(self): - return { - 'a_get_all_user': self.get_all_user, - 'a_get_inactive_user': self.get_inactive_user, - 'a_get_first_user_only': self.get_first_user_only, - 'a_ids_user': self.ids_user, - 'a_ids_user_auth0': self.ids_user_auth0, - } - @staticmethod def from_form(form): - av.val_instance(form, 'form', 'User_Filters.from_form', Form_Filters_User) - get_inactive = av.input_bool(form.active.data, "active", "User_Filters.from_form") + av.val_instance(form, 'form', 'Parameters_User.from_form', Form_Filters_User) + get_inactive = av.input_bool(form.active.data, "active", "Parameters_User.from_form") id_user = form.id_user.data - return User_Filters( + return Parameters_User( get_all_user = (id_user is None), get_inactive_user = get_inactive, - get_first_user_only = False, ids_user = id_user, ids_user_auth0 = '', ) @staticmethod def from_user(user): - av.val_instance(user, 'user', 'User_Filters.from_user', User) - return User_Filters( - get_all_user = (user.id_user is None and user.id_user_auth0 is None), + av.val_instance(user, 'user', 'Parameters_User.from_user', User) + return Parameters_User( + get_all_user = ((user.id_user is None or user.id_user == 0) and user.id_user_auth0 is None), get_inactive_user = False, - get_first_user_only = False, ids_user = user.id_user, ids_user_auth0 = user.id_user_auth0, ) @staticmethod - def get_default(datastore_store): - user = datastore_store.get_user_session() - return User_Filters( + def get_default(): + return Parameters_User( get_all_user = False, get_inactive_user = False, - get_first_user_only = False, - ids_user = user.id_user, - ids_user_auth0 = '', + ids_user = '', + ids_user_auth0 = '' ) """ User_Eval @dataclass @@ -278,3 +270,24 @@ class User_Permission_Evaluation(db.Model): can_edit: {self.can_edit} can_admin: {self.can_admin} ''' + + +class User_Temp(db.Model, Base): + __tablename__ = 'Shop_User_Temp' + __table_args__ = { 'extend_existing': True } + id_user = db.Column(db.Integer, primary_key=True) + id_user_auth0 = db.Column(db.String(255)) + firstname = db.Column(db.String(255)) + surname = db.Column(db.String(255)) + email = db.Column(db.String(255)) + is_email_verified = db.Column(db.Boolean) + is_super_user = db.Column(db.Boolean) + id_currency_default = db.Column(db.Integer) + id_region_default = db.Column(db.Integer) + is_included_VAT_default = db.Column(db.Boolean) + # is_logged_in: bool + + def __init__(self): + self.id_user = 0 + self.is_logged_in = False + super().__init__() \ No newline at end of file diff --git a/controllers/__pycache__/user.cpython-312.pyc b/controllers/__pycache__/user.cpython-312.pyc index cd73e808..39b3bf26 100644 Binary files a/controllers/__pycache__/user.cpython-312.pyc and b/controllers/__pycache__/user.cpython-312.pyc differ diff --git a/controllers/store/manufacturing_purchase_order.py b/controllers/store/manufacturing_purchase_order.py index f4c3cae0..39c0cd17 100644 --- a/controllers/store/manufacturing_purchase_order.py +++ b/controllers/store/manufacturing_purchase_order.py @@ -42,38 +42,6 @@ def manufacturing_purchase_orders(): return redirect(url_for('routes_core.home')) return render_template('pages/store/_manufacturing_purchase_orders.html', model = model, datetime = datetime) -@routes_store_manufacturing_purchase_order.route(Model_View_Store_Manufacturing_Purchase_Order.HASH_GET_STORE_MANUFACTURING_PURCHASE_ORDER, methods=['POST']) -def filter_manufacturing_purchase_order(): - data = Helper_App.get_request_data(request) - try: - form_filters = Filters_Manufacturing_Purchase_Order.from_json(data) - if not form_filters.validate_on_submit(): - error_keys = list(form_filters.errors.keys()) - try: - error_keys.remove(Manufacturing_Purchase_Order.ATTR_ID_PRODUCT_CATEGORY) - except: - pass - try: - error_keys.remove(Manufacturing_Purchase_Order.ATTR_ID_PRODUCT) - except: - pass - if error_keys: - return jsonify({ - Model_View_Store_Manufacturing_Purchase_Order.FLAG_STATUS: Model_View_Store_Manufacturing_Purchase_Order.FLAG_FAILURE, - Model_View_Store_Manufacturing_Purchase_Order.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' - }) - model = Model_View_Store_Manufacturing_Purchase_Order(form_filters_old = form_filters) - if not model.is_user_logged_in: - raise Exception('User not logged in.') - return jsonify({ - Model_View_Store_Manufacturing_Purchase_Order.FLAG_STATUS: Model_View_Store_Manufacturing_Purchase_Order.FLAG_SUCCESS, - Model_View_Store_Manufacturing_Purchase_Order.FLAG_DATA: model.convert_list_objects_to_json(model.manufacturing_purchase_orders) - }) - except Exception as e: - return jsonify({ - Model_View_Store_Manufacturing_Purchase_Order.FLAG_STATUS: Model_View_Store_Manufacturing_Purchase_Order.FLAG_FAILURE, - Model_View_Store_Manufacturing_Purchase_Order.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' - }) @routes_store_manufacturing_purchase_order.route(Model_View_Store_Manufacturing_Purchase_Order.HASH_SAVE_STORE_MANUFACTURING_PURCHASE_ORDER, methods=['POST']) def save_manufacturing_purchase_order(): diff --git a/controllers/store/product.py b/controllers/store/product.py index 2c831e36..7d29403f 100644 --- a/controllers/store/product.py +++ b/controllers/store/product.py @@ -28,79 +28,6 @@ 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(): - Helper_App.console_log('products') - Helper_App.console_log(f'request.args={request.args}') - user = DataStore_Store_Product.get_user_session() - filters = Parameters_Product.get_default(user.id_user) - 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 - Helper_App.console_log(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 - Helper_App.console_log(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: - Helper_App.console_log('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_Filters_Product(data) - if not form_filters.validate_on_submit(): - return jsonify({Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_FAILURE, Model_View_Store_Product.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'}) - # ToDo: manually validate category, product - filters_form = Parameters_Product.from_form_filters_product(form_filters) - model = Model_View_Store_Product(filters = filters_form) - return jsonify({Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_SUCCESS, 'Success': True, Model_View_Store_Product.FLAG_DATA: model.category_list.to_json()}) - except Exception as e: - return jsonify({Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_FAILURE, Model_View_Store_Product.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'}) - -def get_Filters_Product(data_request): - data_form = data_request[Model_View_Store_Product.FLAG_FORM] - form_filters = 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 - Helper_App.console_log(f'data={data}') - try: - form_filters = get_Filters_Product(data) - if not form_filters.validate_on_submit(): - return jsonify({Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_FAILURE, Model_View_Store_Product.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'}) - filters_form = Parameters_Product.from_form(form_filters) - - categories = data[Model_View_Store_Product.FLAG_PRODUCT] - if len(categories) == 0: - return jsonify({Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_FAILURE, Model_View_Store_Product.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) - Helper_App.console_log(f'objsCategory={objsCategory}') - Model_View_Store_Product.save_categories(data.get('comment', 'No comment'), objsCategory) - - model_return = Model_View_Store_Product(filters=filters_form) - Helper_App.console_log('nips') - return jsonify({Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_SUCCESS, 'Success': True, Model_View_Store_Product.FLAG_DATA: model_return.category_list.to_json()}) - except Exception as e: - return jsonify({Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_FAILURE, Model_View_Store_Product.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'}) -""" - - @routes_store_product.route(Model_View_Store_Product.HASH_PAGE_STORE_PRODUCTS, methods=['GET']) def products(): Helper_App.console_log('products') @@ -116,28 +43,6 @@ def products(): return redirect(url_for('routes_core.home')) 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_product(): - data = Helper_App.get_request_data(request) - try: - form_filters = Filters_Product.from_json(data) - if not form_filters.validate_on_submit(): - return jsonify({ - Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_FAILURE, - Model_View_Store_Product.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' - }) - model = Model_View_Store_Product(form_filters_old = form_filters) - if not model.is_user_logged_in: - raise Exception('User not logged in') - return jsonify({ - Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_SUCCESS, - Model_View_Store_Product.FLAG_DATA: model.category_list.to_json() - }) - except Exception as e: - return jsonify({ - Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_FAILURE, - Model_View_Store_Product.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' - }) @routes_store_product.route(Model_View_Store_Product.HASH_SAVE_STORE_PRODUCT, methods=['POST']) def save_product(): diff --git a/controllers/store/product_category.py b/controllers/store/product_category.py index 70859e84..001b7b1f 100644 --- a/controllers/store/product_category.py +++ b/controllers/store/product_category.py @@ -59,32 +59,6 @@ def categories(): return redirect(url_for('routes_core.home')) 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_old = form_filters) - if not model.is_user_logged_in: - raise Exception('User not logged in') - return jsonify({ - Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS, - Model_View_Store_Product_Category.FLAG_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) diff --git a/controllers/store/product_permutation.py b/controllers/store/product_permutation.py index d4baef8c..66fbed19 100644 --- a/controllers/store/product_permutation.py +++ b/controllers/store/product_permutation.py @@ -46,28 +46,6 @@ def permutations(): return redirect(url_for('routes_core.home')) 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_old = form_filters) - if not model.is_user_logged_in: - raise Exception('User not logged in') - return jsonify({ - Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_SUCCESS, - Model_View_Store_Product_Permutation.FLAG_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(): diff --git a/controllers/store/product_variation.py b/controllers/store/product_variation.py index f1b99325..88a8e134 100644 --- a/controllers/store/product_variation.py +++ b/controllers/store/product_variation.py @@ -44,28 +44,6 @@ def product_variations(): return redirect(url_for('routes_core.home')) return render_template('pages/store/_product_variations.html', model = model) -@routes_store_product_variation.route(Model_View_Store_Product_Variation.HASH_GET_STORE_PRODUCT_VARIATION, methods=['POST']) -def filter_product_variation(): - data = Helper_App.get_request_data(request) - try: - form_filters = Filters_Product_Variation.from_json(data) - if not form_filters.validate_on_submit(): - return jsonify({ - Model_View_Store_Product_Variation.FLAG_STATUS: Model_View_Store_Product_Variation.FLAG_FAILURE, - Model_View_Store_Product_Variation.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' - }) - model = Model_View_Store_Product_Variation(form_filters_old = form_filters) - if not model.is_user_logged_in: - raise Exception('User not logged in') - return jsonify({ - Model_View_Store_Product_Variation.FLAG_STATUS: Model_View_Store_Product_Variation.FLAG_SUCCESS, - Model_View_Store_Product_Variation.FLAG_DATA: model.convert_list_objects_to_json(model.variation_types) - }) - except Exception as e: - return jsonify({ - Model_View_Store_Product_Variation.FLAG_STATUS: Model_View_Store_Product_Variation.FLAG_FAILURE, - Model_View_Store_Product_Variation.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' - }) @routes_store_product_variation.route(Model_View_Store_Product_Variation.HASH_SAVE_STORE_PRODUCT_VARIATION, methods=['POST']) def save_product_variation(): diff --git a/controllers/store/stock_item.py b/controllers/store/stock_item.py index e71142c7..613347d9 100644 --- a/controllers/store/stock_item.py +++ b/controllers/store/stock_item.py @@ -44,42 +44,6 @@ def stock_items(): return redirect(url_for('routes_core.home')) return render_template('pages/store/_stock_items.html', model = model, datetime = datetime) -@routes_store_stock_item.route(Model_View_Store_Stock_Item.HASH_GET_STORE_STOCK_ITEM, methods=['POST']) -def filter_stock_item(): - data = Helper_App.get_request_data(request) - try: - form_filters = Filters_Stock_Item.from_json(data) - if not form_filters.validate_on_submit(): - error_keys = list(form_filters.errors.keys()) - try: - error_keys.remove(Stock_Item.ATTR_ID_PRODUCT_CATEGORY) - """ - if not av.val_int(form_filters.id_product_category.data): - form_filters.errors[Stock_Item.ATTR_ID_PRODUCT_CATEGORY] = ['Invalid category.'] - """ - except: - pass - try: - error_keys.remove(Stock_Item.ATTR_ID_PRODUCT) - except: - pass - if error_keys: - return jsonify({ - Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE, - Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' - }) - model = Model_View_Store_Stock_Item(filters_stock_item = form_filters) - if not model.is_user_logged_in: - raise Exception('User not logged in.') - return jsonify({ - Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_SUCCESS, - Model_View_Store_Stock_Item.FLAG_DATA: model.category_list.to_json() - }) - except Exception as e: - return jsonify({ - Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE, - Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' - }) @routes_store_stock_item.route(Model_View_Store_Stock_Item.HASH_SAVE_STORE_STOCK_ITEM, methods=['POST']) def save_stock_item(): diff --git a/controllers/store/supplier.py b/controllers/store/supplier.py index 36dec0a2..c9a8cb92 100644 --- a/controllers/store/supplier.py +++ b/controllers/store/supplier.py @@ -42,38 +42,6 @@ def suppliers(): return redirect(url_for('routes_core.home')) return render_template('pages/store/_suppliers.html', model = model, datetime = datetime) -@routes_store_supplier.route(Model_View_Store_Supplier.HASH_GET_STORE_SUPPLIER, methods=['POST']) -def filter_supplier(): - data = Helper_App.get_request_data(request) - try: - form_filters = Filters_Supplier.from_json(data) - if not form_filters.validate_on_submit(): - error_keys = list(form_filters.errors.keys()) - try: - error_keys.remove(Supplier.ATTR_ID_PRODUCT_CATEGORY) - except: - pass - try: - error_keys.remove(Supplier.ATTR_ID_PRODUCT) - except: - pass - if error_keys: - return jsonify({ - Model_View_Store_Supplier.FLAG_STATUS: Model_View_Store_Supplier.FLAG_FAILURE, - Model_View_Store_Supplier.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' - }) - model = Model_View_Store_Supplier(form_filters_old = form_filters) - if not model.is_user_logged_in: - raise Exception('User not logged in.') - return jsonify({ - Model_View_Store_Supplier.FLAG_STATUS: Model_View_Store_Supplier.FLAG_SUCCESS, - Model_View_Store_Supplier.FLAG_DATA: {supplier.id_supplier: supplier.to_json() for supplier in model.suppliers} - }) - except Exception as e: - return jsonify({ - Model_View_Store_Supplier.FLAG_STATUS: Model_View_Store_Supplier.FLAG_FAILURE, - Model_View_Store_Supplier.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' - }) @routes_store_supplier.route(Model_View_Store_Supplier.HASH_SAVE_STORE_SUPPLIER, methods=['POST']) def save_supplier(): diff --git a/controllers/store/supplier_purchase_order.py b/controllers/store/supplier_purchase_order.py index 392987a6..ba9cdc06 100644 --- a/controllers/store/supplier_purchase_order.py +++ b/controllers/store/supplier_purchase_order.py @@ -42,38 +42,6 @@ def supplier_purchase_orders(): return redirect(url_for('routes_core.home')) return render_template('pages/store/_supplier_purchase_orders.html', model = model, datetime = datetime) -@routes_store_supplier_purchase_order.route(Model_View_Store_Supplier_Purchase_Order.HASH_GET_STORE_SUPPLIER_PURCHASE_ORDER, methods=['POST']) -def filter_supplier_purchase_order(): - data = Helper_App.get_request_data(request) - try: - form_filters = Filters_Supplier_Purchase_Order.from_json(data) - if not form_filters.validate_on_submit(): - error_keys = list(form_filters.errors.keys()) - try: - error_keys.remove(Supplier_Purchase_Order.ATTR_ID_PRODUCT_CATEGORY) - except: - pass - try: - error_keys.remove(Supplier_Purchase_Order.ATTR_ID_PRODUCT) - except: - pass - if error_keys: - return jsonify({ - Model_View_Store_Supplier_Purchase_Order.FLAG_STATUS: Model_View_Store_Supplier_Purchase_Order.FLAG_FAILURE, - Model_View_Store_Supplier_Purchase_Order.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' - }) - model = Model_View_Store_Supplier_Purchase_Order(form_filters_old = form_filters) - if not model.is_user_logged_in: - raise Exception('User not logged in.') - return jsonify({ - Model_View_Store_Supplier_Purchase_Order.FLAG_STATUS: Model_View_Store_Supplier_Purchase_Order.FLAG_SUCCESS, - Model_View_Store_Supplier_Purchase_Order.FLAG_DATA: model.convert_list_objects_to_dict_json_by_attribute_key_default(model.supplier_purchase_orders) - }) - except Exception as e: - return jsonify({ - Model_View_Store_Supplier_Purchase_Order.FLAG_STATUS: Model_View_Store_Supplier_Purchase_Order.FLAG_FAILURE, - Model_View_Store_Supplier_Purchase_Order.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' - }) @routes_store_supplier_purchase_order.route(Model_View_Store_Supplier_Purchase_Order.HASH_SAVE_STORE_SUPPLIER_PURCHASE_ORDER, methods=['POST']) def save_supplier_purchase_order(): diff --git a/controllers/user.py b/controllers/user.py index 0e388f49..747db117 100644 --- a/controllers/user.py +++ b/controllers/user.py @@ -14,7 +14,7 @@ Initializes the Flask application, sets the configuration based on the environme # 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 business_objects.user import User, Parameters_User from datastores.datastore_user import DataStore_User from helpers.helper_app import Helper_App import lib.argument_validation as av @@ -154,9 +154,9 @@ def login_callback(): Helper_App.console_log(f'user ID: {id_user}') """ user = User.from_json_auth0(token) # datastore_user.get_user_auth0() - user_filters = User_Filters.from_user(user) + filters = Parameters_User.from_user(user) datastore_user = DataStore_User() - users, errors = datastore_user.get_many_user(user_filters, user) + users, errors = datastore_user.get_many_user(filters, user) try: user = users[0] Helper_App.console_log('User logged in') @@ -166,7 +166,7 @@ def login_callback(): session[Model_View_Base.FLAG_USER] = user_json Helper_App.console_log(f'user stored on session') except: - Helper_App.console_log(f'User not found: {user_filters}\nDatabase query error: {errors}') + Helper_App.console_log(f'User not found: {Parameters_User}\nDatabase query error: {errors}') try: hash_callback = token.get('hash_callback') @@ -231,7 +231,16 @@ def logout_callback(): @routes_user.route("/user") def user(): try: - model = Model_View_User(current_app, db) + model = Model_View_User() + for currency in model.currencies: + if currency.id_currency == model.user.id_currency_default: + model.user.currency_default = currency + break + for region in model.regions: + if region.id_region == model.user.id_region_default: + model.user.region_default = region + break + model.users = [model.user] if not model.is_user_logged_in: # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_User.FLAG_CALLBACK: Model_View_User.HASH_PAGE_USER_ACCOUNT }))) return redirect(url_for('routes_core.home')) diff --git a/datastores/__pycache__/datastore_base.cpython-312.pyc b/datastores/__pycache__/datastore_base.cpython-312.pyc index c9eb0f7e..4a8def23 100644 Binary files a/datastores/__pycache__/datastore_base.cpython-312.pyc and b/datastores/__pycache__/datastore_base.cpython-312.pyc differ diff --git a/datastores/__pycache__/datastore_store_base.cpython-312.pyc b/datastores/__pycache__/datastore_store_base.cpython-312.pyc index 1c69cf60..90a724f0 100644 Binary files a/datastores/__pycache__/datastore_store_base.cpython-312.pyc and b/datastores/__pycache__/datastore_store_base.cpython-312.pyc differ diff --git a/datastores/__pycache__/datastore_user.cpython-312.pyc b/datastores/__pycache__/datastore_user.cpython-312.pyc index 2b9600aa..6ed0f141 100644 Binary files a/datastores/__pycache__/datastore_user.cpython-312.pyc and b/datastores/__pycache__/datastore_user.cpython-312.pyc differ diff --git a/datastores/datastore_base.py b/datastores/datastore_base.py index bf8deff9..fc3cf895 100644 --- a/datastores/datastore_base.py +++ b/datastores/datastore_base.py @@ -20,15 +20,15 @@ from business_objects.store.product_category import Product_Category_Container, from business_objects.store.currency import Currency from business_objects.store.image import Image from business_objects.store.delivery_option import Delivery_Option -from business_objects.store.delivery_region import Region from business_objects.store.discount import Discount from business_objects.store.order import Order from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product # Permutation_Variation_Link """ +from business_objects.region import Region from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item from business_objects.unit_measurement import Unit_Measurement -from business_objects.user import User, User_Filters, User_Permission_Evaluation +from business_objects.user import User, Parameters_User, User_Permission_Evaluation # from helpers.helper_db_mysql import Helper_DB_MySQL # from models.model_view_store_checkout import Model_View_Store_Checkout # circular! from extensions import db @@ -155,23 +155,57 @@ class DataStore_Base(BaseModel): @staticmethod def get_user_session(): Helper_App.console_log('DataStore_Base.get_user_session') - return User.from_json(session.get(User.FLAG_USER)) - user = User.get_default() - try: - Helper_App.console_log(f'user session: {session[self.app.ID_TOKEN_USER]}') - info_user = session[self.app.ID_TOKEN_USER].get('userinfo') - Helper_App.console_log(f'info_user: {info_user}') - user.is_logged_in = ('sub' in list(info_user.keys()) and not info_user['sub'] == '' and not str(type(info_user['sub'])) == " 0: + errors = [SQL_Error.from_DB_record(row) for row in result_set_e] # (row[0], row[1]) + for error in errors: + Helper_App.console_log(f"Error [{error.code}]: {error.msg}") + + DataStore_Base.db_cursor_clear(cursor) + cursor.close() + + return users, errors @staticmethod def upload_bulk(permanent_table_name, records, batch_size): _m = 'DataStore_Base.upload_bulk' @@ -282,4 +316,30 @@ class DataStore_Base(BaseModel): DataStore_Base.db_cursor_clear(cursor) cursor.close() - return units, errors \ No newline at end of file + return units, errors + + @classmethod + def get_many_region(cls, get_inactive = False): + _m = 'DataStore_Store_Base.get_many_region' + _m_db_region = 'p_shop_get_many_region' + + argument_dict_list_region = { + 'a_get_inactive_region': 1 if get_inactive else 0 + } + + Helper_App.console_log(f'executing {_m_db_region}') + result = cls.db_procedure_execute(_m_db_region, argument_dict_list_region) + cursor = result.cursor + Helper_App.console_log('data received') + + # cursor.nextset() + result_set_1 = cursor.fetchall() + regions = [] + for row in result_set_1: + region = Region.from_DB_region(row) + regions.append(region) + Helper_App.console_log(f'regions: {regions}') + DataStore_Base.db_cursor_clear(cursor) + cursor.close() + + return regions \ No newline at end of file diff --git a/datastores/datastore_store_base.py b/datastores/datastore_store_base.py index d9a8e5b9..235fd74e 100644 --- a/datastores/datastore_store_base.py +++ b/datastores/datastore_store_base.py @@ -25,7 +25,6 @@ from business_objects.store.product import Product, Product_Permutation, Paramet from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item from business_objects.store.storage_location import Storage_Location -from business_objects.user import User, User_Filters, User_Permission_Evaluation from business_objects.store.product_variation import Product_Variation, Parameters_Product_Variation from business_objects.store.product_variation_type import Product_Variation_Type from datastores.datastore_base import DataStore_Base @@ -274,32 +273,6 @@ class DataStore_Store_Base(DataStore_Base): return currencies - @classmethod - def get_many_region(cls, get_inactive = False): - _m = 'DataStore_Store_Base.get_many_region' - _m_db_region = 'p_shop_get_many_region' - - argument_dict_list_region = { - 'a_get_inactive_region': 1 if get_inactive else 0 - } - - Helper_App.console_log(f'executing {_m_db_region}') - result = cls.db_procedure_execute(_m_db_region, argument_dict_list_region) - cursor = result.cursor - Helper_App.console_log('data received') - - # cursor.nextset() - result_set_1 = cursor.fetchall() - regions = [] - for row in result_set_1: - region = Region.from_DB_region(row) - regions.append(region) - Helper_App.console_log(f'regions: {regions}') - DataStore_Store_Base.db_cursor_clear(cursor) - cursor.close() - - return regions - @classmethod def get_many_region_and_currency(cls, get_inactive_currency = False, get_inactive_region = False): _m = 'DataStore_Store_Base.get_many_region_and_currency' diff --git a/datastores/datastore_user.py b/datastores/datastore_user.py index b9e98b61..42e1a523 100644 --- a/datastores/datastore_user.py +++ b/datastores/datastore_user.py @@ -15,8 +15,9 @@ Datastore for Users import lib.argument_validation as av from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item -from business_objects.user import User, User_Filters, User_Permission_Evaluation -from datastores.datastore_base import DataStore_Base +from business_objects.user import User, Parameters_User, User_Permission_Evaluation +# from datastores.datastore_base import DataStore_Base +from datastores.datastore_store_base import DataStore_Store_Base from helpers.helper_app import Helper_App from helpers.helper_db_mysql import Helper_DB_MySQL # from models.model_view_store_checkout import Model_View_Store_Checkout # circular! @@ -35,7 +36,7 @@ from datetime import datetime db = SQLAlchemy() -class DataStore_User(DataStore_Base): +class DataStore_User(DataStore_Store_Base): # Global constants # Attributes @@ -120,7 +121,7 @@ class DataStore_User(DataStore_Base): Helper_App.console_log(_m) # av.val_str(user_filters, 'user_filters', _m) # av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1) - av.val_instance(user_filters, 'user_filters', _m, User_Filters) + av.val_instance(user_filters, 'user_filters', _m, Parameters_User) guid = Helper_DB_MySQL.create_guid() # now = datetime.now() @@ -188,7 +189,7 @@ class DataStore_User(DataStore_Base): Helper_App.console_log(_m) # av.val_str(user_filters, 'user_filters', _m) # av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1) - av.val_instance(user_filters, 'user_filters', _m, User_Filters) + av.val_instance(user_filters, 'user_filters', _m, Parameters_User) guid = Helper_DB_MySQL.create_guid() # now = datetime.now() diff --git a/helpers/__pycache__/helper_app.cpython-312.pyc b/helpers/__pycache__/helper_app.cpython-312.pyc index 1900ccb8..03d538fc 100644 Binary files a/helpers/__pycache__/helper_app.cpython-312.pyc and b/helpers/__pycache__/helper_app.cpython-312.pyc differ diff --git a/models/__pycache__/model_view_base.cpython-312.pyc b/models/__pycache__/model_view_base.cpython-312.pyc index f1ff8428..72fa3580 100644 Binary files a/models/__pycache__/model_view_base.cpython-312.pyc and b/models/__pycache__/model_view_base.cpython-312.pyc differ diff --git a/models/__pycache__/model_view_user.cpython-312.pyc b/models/__pycache__/model_view_user.cpython-312.pyc index 4f2a389e..5bd2c968 100644 Binary files a/models/__pycache__/model_view_user.cpython-312.pyc and b/models/__pycache__/model_view_user.cpython-312.pyc differ diff --git a/models/model_view_base.py b/models/model_view_base.py index 48f266b7..df1cabcd 100644 --- a/models/model_view_base.py +++ b/models/model_view_base.py @@ -19,7 +19,7 @@ Base data model for views # from routes import bp_home from business_objects.base import Base from business_objects.store.product_category import Product_Category -from business_objects.user import User, User_Filters +from business_objects.user import User, Parameters_User from datastores.datastore_base import DataStore_Base from datastores.datastore_user import DataStore_User from forms.access_level import Filters_Access_Level @@ -94,6 +94,7 @@ class Model_View_Base(BaseModel, ABC): FLAG_HAMBURGER: ClassVar[str] = 'hamburger' FLAG_IMAGE_LOGO: ClassVar[str] = 'image-logo' FLAG_INITIALISED: ClassVar[str] = 'initialised' + FLAG_IS_INCLUDED_VAT: ClassVar[str] = 'is_included_VAT' # FLAG_KEY_PRIMARY: ClassVar[str] = Store_Base.FLAG_KEY_PRIMARY FLAG_MESSAGE: ClassVar[str] = 'Message' FLAG_MODAL: ClassVar[str] = 'modal' @@ -300,7 +301,7 @@ class Model_View_Base(BaseModel, ABC): datastore_store = DataStore_Store() user = datastore_store.get_user_session() if not user.is_logged_in: return False - filters_user = User_Filters.from_user(user) # get_default(datastore_store) + filters_user = Parameters_User.from_user(user) # get_default(datastore_store) users, errors = datastore_store.get_many_user(filters_user) try: user = users[0] @@ -314,7 +315,7 @@ class Model_View_Base(BaseModel, ABC): datastore_store = DataStore_Store() user = datastore_store.get_user_session() if not user.is_logged_in: return False - filters_user = User_Filters.from_user(user) # .get_default(datastore_store) + filters_user = Parameters_User.from_user(user) # .get_default(datastore_store) users, errors = datastore_store.get_many_user(filters_user) try: user = users[0] diff --git a/models/model_view_user.py b/models/model_view_user.py index fbecc8d2..eb851254 100644 --- a/models/model_view_user.py +++ b/models/model_view_user.py @@ -11,21 +11,31 @@ Data model for user view """ # internal -from models.model_view_base import Model_View_Base +from datastores.datastore_user import DataStore_User +# from models.model_view_base import Model_View_Base +from models.model_view_store import Model_View_Store # from routes import bp_home # external from typing import ClassVar -class Model_View_User(Model_View_Base): +class Model_View_User(Model_View_Store): FLAG_ERROR_OAUTH: ClassVar[str] = 'error' FLAG_ERROR_DESCRIPTION_OAUTH: ClassVar[str] = 'error_description' + FLAG_FIRSTNAME: ClassVar[str] = 'firstname' + FLAG_SURNAME: ClassVar[str] = 'surname' FLAG_STATE_OAUTH: ClassVar[str] = 'state' # Attributes + currencies: list = None + regions: list = None + users: list = None @property def title(self): return 'User' - def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_USER_ACCOUNT): + def __init__(self, hash_page_current=Model_View_Store.HASH_PAGE_USER_ACCOUNT): # Constructor - super().__init__(hash_page_current=hash_page_current) + super().__init__(hash_page_current=hash_page_current, form_filters_old = None) + datastore_user = DataStore_User() + self.currencies = datastore_user.get_many_currency() + self.regions = datastore_user.get_many_region() \ No newline at end of file diff --git a/static/MySQL/0000_combined.sql b/static/MySQL/0000_combined.sql index 1db172e4..d6226fca 100644 --- a/static/MySQL/0000_combined.sql +++ b/static/MySQL/0000_combined.sql @@ -118,6 +118,7 @@ DROP TABLE IF EXISTS Shop_User_Address; DROP TABLE IF EXISTS Shop_User_Role_Link_Audit; DROP TABLE IF EXISTS Shop_User_Role_Link; +DROP TABLE IF EXISTS Shop_User_Temp; DROP TABLE IF EXISTS Shop_User_Audit; DROP TABLE IF EXISTS Shop_User; @@ -2527,9 +2528,9 @@ SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning CREATE TABLE IF NOT EXISTS Shop_User ( id_user INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id_user_auth0 VARCHAR(200) NOT NULL, - firstname VARCHAR(255) NOT NULL, - surname VARCHAR(255) NOT NULL, - email VARCHAR(254) NOT NULL, + firstname VARCHAR(255) NULL, + surname VARCHAR(255) NULL, + email VARCHAR(254) NULL, is_email_verified BIT NOT NULL DEFAULT 0, is_super_user BIT NOT NULL DEFAULT 0, id_currency_default INT NULL, @@ -2570,6 +2571,31 @@ CREATE TABLE IF NOT EXISTS Shop_User_Audit ( ON UPDATE RESTRICT ); +-- File: 1314_tbl_Shop_User_Temp.sql + +# Users Temp + +-- DROP TABLE IF EXISTS Shop_User_Temp; + +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_User_Temp'; + +CREATE TABLE IF NOT EXISTS Shop_User_Temp ( + id_temp INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user INT NOT NULL + , id_user_auth0 VARCHAR(200) NOT NULL + , firstname VARCHAR(255) + , surname VARCHAR(255) + , email VARCHAR(254) + , is_email_verified BIT + , is_super_user BIT + , id_currency_default INT + , id_region_default INT + , is_included_VAT_default BIT + , active BIT + , guid BINARY(36) NOT NULL +); + + -- File: 1315_tbl_Shop_User_Role_Link.sql # User Role link @@ -8584,19 +8610,14 @@ BEGIN DECLARE exit handler for SQLEXCEPTION BEGIN - -- Get diagnostic information GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE , @errno = MYSQL_ERRNO , @text = MESSAGE_TEXT ; - -- Rollback the transaction ROLLBACK; - -- Select the error information - -- SELECT 'Error' AS status, @errno AS error_code, @sqlstate AS sql_state, @text AS message; - CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT , id_type INT NULL @@ -8691,7 +8712,7 @@ BEGIN SELECT v_id_type_error_bad_data , v_code_type_error_bad_data - , CONCAT('The following category(s) do not have a code: ', GROUP_CONCAT(IFNULL(t_C.name_error, 'NULL') SEPARATOR ', ')) AS msg + , CONCAT('The following category(s) do not have a code: ', GROUP_CONCAT(t_C.name_error SEPARATOR ', ')) AS msg FROM tmp_Category t_C WHERE ISNULL(t_C.code) ; @@ -8706,7 +8727,7 @@ BEGIN SELECT v_id_type_error_bad_data , v_code_type_error_bad_data - , CONCAT('The following category(s) do not have a name: ', GROUP_CONCAT(IFNULL(t_C.name_error, 'NULL') SEPARATOR ', ')) AS msg + , CONCAT('The following category(s) do not have a name: ', GROUP_CONCAT(t_C.name_error SEPARATOR ', ')) AS msg FROM tmp_Category t_C WHERE ISNULL(t_C.name) ; @@ -8721,7 +8742,7 @@ BEGIN SELECT v_id_type_error_bad_data , v_code_type_error_bad_data - , CONCAT('The following category(s) do not have a display order: ', GROUP_CONCAT(IFNULL(t_C.name_error, 'NULL') SEPARATOR ', ')) AS msg + , CONCAT('The following category(s) do not have a display order: ', GROUP_CONCAT(t_C.name_error SEPARATOR ', ')) AS msg FROM tmp_Category t_C WHERE ISNULL(t_C.display_order) ; @@ -11466,7 +11487,9 @@ BEGIN ; UPDATE Shop_Product_Permutation PP - INNER JOIN tmp_Permutation t_P ON PP.id_permutation = t_P.id_permutation + INNER JOIN tmp_Permutation t_P + ON PP.id_permutation = t_P.id_permutation + AND t_P.is_new = 0 SET PP.id_product = t_P.id_product , PP.description = t_P.description @@ -15820,187 +15843,282 @@ CALL p_shop_get_many_stripe_price_new ( -- File: 7312_p_shop_save_user.sql - - -/* - -CALL p_shop_edit_user ( - 'auth0|6582b95c895d09a70ba10fef', # a_id_user - '', # a_name - '', # a_email - 0 # a_email_verified -) - -*/ - - --- Clear previous proc -DROP PROCEDURE IF EXISTS p_shop_edit_user; + +DROP PROCEDURE IF EXISTS p_shop_save_user; DELIMITER // -CREATE PROCEDURE p_shop_edit_user ( - IN a_id_user INT, - IN a_name VARCHAR(255), - IN a_email VARCHAR(254), - IN a_email_verified BIT +CREATE PROCEDURE p_shop_save_user ( + IN a_comment VARCHAR(500), + IN a_guid BINARY(36), + IN a_id_user INT, + IN a_debug BIT ) BEGIN - -- Argument redeclaration - -- Variable declaration - DECLARE v_has_filter_user BIT; - -- DECLARE v_now DATETIME; + DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_id_permission_product INT; + DECLARE v_id_permission_user_admin LONGTEXT; + DECLARE v_id_change_set INT; + DECLARE v_id_access_level_edit INT; + DECLARE v_can_admin_user BIT; + DECLARE v_time_start TIMESTAMP(6); + DECLARE exit handler for SQLEXCEPTION + BEGIN + GET DIAGNOSTICS CONDITION 1 + @sqlstate = RETURNED_SQLSTATE + , @errno = MYSQL_ERRNO + , @text = MESSAGE_TEXT + ; + + ROLLBACK; + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + MET.id_type + , @errno + , @text + FROM partsltd_prod.Shop_Msg_Error_Type MET + WHERE MET.code = 'MYSQL_ERROR' + ; + SELECT * + FROM tmp_Msg_Error; + DROP TABLE IF EXISTS tmp_Msg_Error; + END; - -- Argument validation + default values - IF a_id_user IS NULL THEN - SET a_id_user = ''; - ELSE - SET a_id_user = TRIM(a_id_user); - END IF; - IF a_name IS NULL THEN - SET a_name = ''; - ELSE - SET a_name = TRIM(a_name); - END IF; - IF a_email IS NULL THEN - SET a_email = ''; - ELSE - SET a_email = TRIM(a_email); - END IF; - IF a_email_verified IS NULL THEN - SET a_email_verified = 0; - END IF; + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_id_type_error_bad_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_type_error_bad_data LIMIT 1); + SET v_id_access_level_edit := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'EDIT' LIMIT 1); + SET v_id_permission_user_admin := (SELECT GROUP_CONCAT(id_permission SEPARATOR ',') FROM Shop_Permission WHERE code = 'STORE_USER_ADMIN' LIMIT 1); + CALL p_validate_guid ( a_guid ); - -- Temporary tables DROP TABLE IF EXISTS tmp_Msg_Error; - DROP TABLE IF EXISTS tmp_Shop_User; + DROP TABLE IF EXISTS tmp_User; - CREATE TABLE tmp_Shop_User ( - id_user INT NOT NULL, - CONSTRAINT FK_tmp_Shop_User_id_user - FOREIGN KEY (id_user) - REFERENCES Shop_User(id_user), - active BIT NOT NULL + CREATE TABLE tmp_User ( + id_user INT NOT NULL + , id_user_auth0 VARCHAR(200) NOT NULL + , firstname VARCHAR(255) + , surname VARCHAR(255) + , email VARCHAR(254) + , is_email_verified BIT NOT NULL + , is_super_user BIT NOT NULL + , id_currency_default INT + , id_region_default INT + , is_included_VAT_default BIT + , active BIT NOT NULL + , name_error VARCHAR(1000) ); CREATE TABLE tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, id_type INT NOT NULL, - # code VARCHAR(50) NOT NULL, - # CONSTRAINT chk_tmp_Msg_Error_code CHECK (code IN (SELECT code FROM Shop_Msg_Error_Type)), - CONSTRAINT FK_tmp_Msg_Error_id_type - FOREIGN KEY (id_type) - REFERENCES Shop_Msg_Error_Type(id_type), + code VARCHAR(50) NOT NULL, msg VARCHAR(4000) NOT NULL ); - - -- Parse filters - SET v_has_filter_user = CASE WHEN a_id_user = '' THEN 0 ELSE 1 END; - - - -- User - IF v_has_filter_user THEN - INSERT INTO tmp_Shop_User ( - id_user, - active - ) - SELECT id_user, - active - FROM Shop_User - WHERE id_user LIKE CONCAT('%', a_id_user, '%') - AND active - LIMIT 1 - ; - - IF NOT EXISTS (SELECT id_user FROM tmp_Shop_User LIMIT 1) THEN - INSERT INTO Shop_User ( - id_user, - name, - email, - email_verified - ) - VALUES ( - a_id_user, - a_name, - a_email, - a_email_verified - ); - - INSERT INTO tmp_Shop_User ( - id_user, - active - ) - SELECT id_user, - active - FROM Shop_User - WHERE id_user LIKE CONCAT('%', a_id_user, '%') - AND active - LIMIT 1 - ; - END IF; - - SET a_id_user := (SELECT id_user FROM tmp_Shop_User LIMIT 1); - ELSE - INSERT INTO tmp_Msg_Error ( - id_type, - msg - ) - VALUES ( - (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1), - 'No user ID provided.' - ) - ; - END IF; - - - /* - IF NOT EXISTS (SELECT msg FROM tmp_Msg_Error LIMIT 1) THEN - END IF; - */ - - - -- Returns - # User - SELECT * - FROM tmp_Shop_User + -- Get data from Temp table + INSERT INTO tmp_User ( + id_user + , id_user_auth0 + , firstname + , surname + , email + , is_email_verified + , is_super_user + , id_currency_default + , id_region_default + , is_included_VAT_default + , active + ) + SELECT + U_T.id_user + , U_T.id_user_auth0 + , IFNULL(U_T.firstname, U.firstname) AS firstname + , IFNULL(U_T.surname, U.surname) AS surname + , IFNULL(U_T.email, U.email) AS email + , IFNULL(U_T.is_email_verified, U.is_email_verified) AS is_email_verified + , IFNULL(U_T.is_super_user, U.is_super_user) AS is_super_user + , IFNULL(U_T.id_currency_default, U.id_currency_default) AS id_currency_default + , IFNULL(U_T.id_region_default, U.id_region_default) AS id_region_default + , IFNULL(U_T.is_included_VAT_default, U.is_included_VAT_default) AS is_included_VAT_default + , IFNULL(IFNULL(U_T.active, U.active), 1) AS active + , IFNULL(U_T.display_order, PC.display_order) AS display_order + FROM partsltd_prod.Shop_User_Temp U_T + LEFT JOIN Shop_User U ON U_T.id_user = U.id_user + WHERE U_T.guid = a_guid ; + + UPDATE tmp_User t_U + SET + t_U.name_error = IFNULL(t_U.email, t_U.id_user_auth0) + ; + + -- Validation + -- Missing mandatory fields + -- email + IF EXISTS (SELECT * FROM tmp_User t_U WHERE ISNULL(t_U.email) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following User(s) do not have an email: ', GROUP_CONCAT(t_U.name_error SEPARATOR ', ')) AS msg + FROM tmp_User t_U + WHERE ISNULL(t_U.email) + ; + END IF; + -- is_super_user + IF EXISTS (SELECT * FROM tmp_User t_U WHERE ISNULL(t_U.is_super_user) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following User(s) do not have an is super user field: ', GROUP_CONCAT(t_U.name_error SEPARATOR ', ')) AS msg + FROM tmp_User t_U + WHERE ISNULL(t_U.is_super_user) + ; + END IF; + -- is_email_verified + IF EXISTS (SELECT * FROM tmp_User t_U WHERE ISNULL(t_U.is_email_verified) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following User(s) do not have an is email verified: ', GROUP_CONCAT(t_U.name_error SEPARATOR ', ')) AS msg + FROM tmp_User t_U + WHERE ISNULL(t_U.is_email_verified) + ; + END IF; + + + -- Permissions + IF a_debug = 1 THEN + SELECT + a_guid -- GUID + , a_id_user -- ID User + , FALSE -- get inactive Users + , v_id_permission_user_admin -- IDs Permission + , v_id_access_level_edit -- ID Access Level + , NULL -- IDs Product + ; + END IF; + + CALL p_shop_calc_user( + a_guid -- GUID + , a_id_user -- ID User + , FALSE -- get inactive Users + , v_id_permission_user_admin -- IDs Permission + , v_id_access_level_edit -- ID Access Level + , NULL -- IDs Product + ); + + SET v_can_admin_user := ( + SELECT IFNULL(UE_T.can_edit, 0) = 1 + FROM partsltd_prod.Shop_User_Eval_Temp UE_T + WHERE + UE_T.GUID = a_guid + AND UE_T.id_user = a_id_user + AND UE_T.id_permission = v_id_permission_user_admin + ); + + IF (v_can_admin_user = 0 AND EXISTS ( + SELECT * + FROM tmp_User t_U + WHERE + t_U.id_user <> a_id_user + )) THEN + DELETE FROM tmp_Msg_Error; + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + VALUES ( + v_id_type_error_no_permission + , v_code_type_error_no_permission + , 'You do not have permission to edit other Users.' + ) + ; + END IF; + + CALL p_shop_clear_calc_user(a_guid); + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + START TRANSACTION; + + INSERT INTO Shop_User_Change_Set ( comment ) + VALUES ( a_comment ) + ; + + SET v_id_change_set := LAST_INSERT_ID(); + + UPDATE Shop_User U + INNER JOIN tmp_User t_U ON U.id_user = t_U.id_user + SET + U.id_user_auth0 = t_U.id_user_auth0 + , U.firstname = t_U.firstname + , U.surname = t_U.surname + , U.email = t_U.email + , U.is_email_verified = t_U.is_email_verified + , U.is_super_user = t_U.is_super_user + , U.id_currency_default = t_U.id_currency_default + , U.id_region_default = t_U.id_region_default + , U.is_included_VAT_default = t_U.is_included_VAT_default + , U.active = t_U.active + , U.id_change_set = v_id_change_set + ; + + DELETE FROM Shop_User_Temp + WHERE GUID = a_guid; + + COMMIT; + END IF; # Errors SELECT * - FROM tmp_Msg_Error - ; + FROM tmp_Msg_Error t_ME + INNER JOIN partsltd_prod.Shop_Msg_Error_Type MET ON t_ME.id_type = MET.id_type + ; - /* - # Return arguments for test - SELECT a_id_user, - a_name, - a_email, - a_email_verified - ; - */ - - -- Clean up + IF a_debug = 1 THEN + SELECT * from tmp_User; + END IF; + DROP TABLE IF EXISTS tmp_Msg_Error; - DROP TABLE IF EXISTS tmp_Shop_User; + DROP TABLE IF EXISTS tmp_User; + + IF a_debug = 1 THEN + CALL partsltd_prod.p_debug_timing_reporting ( v_time_start ); + END IF; END // DELIMITER ;; -/* - -CALL p_shop_edit_user ( - '', - '', - '', - 0 -) - -*/ - - -- File: 7313_p_get_many_user.sql @@ -16014,7 +16132,6 @@ CREATE PROCEDURE p_get_many_user ( , IN a_id_user_auth0 VARCHAR(200) , IN a_get_all_user BIT , IN a_get_inactive_user BIT - , IN a_get_first_user_only BIT , IN a_ids_user LONGTEXT , IN a_ids_user_auth0 LONGTEXT , IN a_debug BIT @@ -16026,7 +16143,6 @@ BEGIN DECLARE v_id_permission_user INT; DECLARE v_id_permission_user_admin INT; DECLARE v_ids_permission_required VARCHAR(4000); - DECLARE v_now DATETIME; DECLARE v_id_minimum INT; DECLARE v_code_error_bad_data VARCHAR(50); DECLARE v_id_type_error_bad_data INT; @@ -16035,6 +16151,7 @@ BEGIN DECLARE v_guid BINARY(36); DECLARE v_rank_max INT; DECLARE v_time_start TIMESTAMP(6); + DECLARE v_is_new BIT; SET v_time_start := CURRENT_TIMESTAMP(6); SET v_guid := UUID(); @@ -16046,10 +16163,11 @@ BEGIN SET v_code_error_bad_data := (SELECT code FROM partsltd_prod.Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); SET v_id_type_error_bad_data := (SELECT id_type FROM partsltd_prod.Shop_Msg_Error_Type WHERE code = v_code_error_bad_data LIMIT 1); SET v_ids_permission_required := CONCAT(v_id_permission_user, ',', v_id_permission_user_admin, ',', v_id_permission_store_admin); + SET v_is_new := FALSE; SET a_get_all_user := IFNULL(a_get_all_user, 1); SET a_get_inactive_user := IFNULL(a_get_inactive_user, 0); - SET a_get_first_user_only := IFNULL(a_get_first_user_only, 0); + -- SET a_get_first_user_only := IFNULL(a_get_first_user_only, 0); SET a_ids_user := TRIM(IFNULL(a_ids_user, '')); SET a_ids_user_auth0 := TRIM(IFNULL(a_ids_user_auth0, '')); SET a_debug := IFNULL(a_debug, 0); @@ -16060,7 +16178,7 @@ BEGIN , a_id_user_auth0 , a_get_all_user , a_get_inactive_user - , a_get_first_user_only + -- , a_get_first_user_only , a_ids_user , a_ids_user_auth0 , a_debug @@ -16095,17 +16213,33 @@ BEGIN END IF; IF ISNULL(a_id_user) THEN - INSERT INTO tmp_Msg_Error ( - id_type, - code, - msg - ) - VALUES ( - v_id_type_error_bad_data, - v_code_error_bad_data, - CONCAT('User ID required for authorisation.') - ) - ; + IF NOT ISNULL(a_id_user_auth0) THEN + INSERT INTO partsltd_prod.Shop_User ( + id_user_auth0 + , is_super_user + , active + ) + VALUES ( + a_id_user_auth0 + , 0 -- is_super_user + , 1 -- active + ) + ; + SET a_id_user := (SELECT U.id_user FROM partsltd_prod.Shop_User U WHERE U.id_user_auth0 = a_id_user_auth0 LIMIT 1); + SET v_is_new := TRUE; + ELSE + INSERT INTO tmp_Msg_Error ( + id_type, + code, + msg + ) + VALUES ( + v_id_type_error_bad_data, + v_code_error_bad_data, + CONCAT('User ID required for authorisation.') + ) + ; + END IF; END IF; SET v_has_filter_user := CASE WHEN a_ids_user = '' THEN 0 ELSE 1 END; @@ -16272,6 +16406,7 @@ BEGIN SELECT * FROM tmp_User; END IF; + /* IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN IF a_get_first_user_only THEN DELETE t_U @@ -16280,6 +16415,7 @@ BEGIN ; END IF; END IF; + */ IF a_debug = 1 THEN SELECT * FROM tmp_User; @@ -16444,6 +16580,7 @@ BEGIN , U.is_super_user , t_U.can_admin_store , t_U.can_admin_user + , v_is_new AS is_new FROM tmp_User t_U INNER JOIN partsltd_prod.Shop_User U ON t_U.id_user = U.id_user ; @@ -16482,13 +16619,22 @@ DELIMITER ;; -CALL p_get_many_user (NULL, 'google-oauth2|109567376920138999933', False, False, False, NULL, 'google-oauth2|109567376920138999933', 0); +CALL p_get_many_user ( + NULL + , 'google-oauth2|109567376920138999933' + , False + , False + -- , False + , NULL + , 'google-oauth2|109567376920138999933' + , 0 +); /* NULL # a_id_user , 'auth0|6582b95c895d09a70ba10fef' # a_id_user_auth0 , 0 # a_get_all_user , 0 # a_get_inactive_user - , 0 # a_get_first_user_only + -- , 0 # a_get_first_user_only , NULL # a_ids_user , 'auth0|6582b95c895d09a70ba10fef' # a_ids_user_auth0 , 0 -- a_debug @@ -16506,7 +16652,7 @@ CALL p_get_many_user( , 'auth0|6582b95c895d09a70ba10fef' -- :a_id_user_auth0, , 1 -- :a_get_all_user, , 0 -- :a_get_inactive_user, - , 0 -- :a_get_first_user_only, + -- , 0 -- :a_get_first_user_only, , NULL -- :a_ids_user, , 'auth0|6582b95c895d09a70ba10fef' -- :a_ids_user_auth0 ); @@ -24265,12 +24411,34 @@ INSERT INTO Shop_User ( , firstname , surname , email - # email_verified , is_super_user + , active ) VALUES - ('auth0|6582b95c895d09a70ba10fef', 'Teddy', 'Middleton-Smith', 'edward.middletonsmith@gmail.com', 1), - ('parts_guest', 'Guest', '', '', 0) + ( + 'auth0|6582b95c895d09a70ba10fef' -- id_user_auth0 + , 'Teddy' -- firstname + , 'Middleton-Smith' -- surname + , 'edward.middletonsmith@gmail.com' -- email + , 1 -- is_super_user + , 1 -- active + ), + ( + 'parts_guest' -- id_user_auth0 + , 'Guest' -- firstname + , '' -- surname + , '' -- email + , 0 -- is_super_user + , 1 -- active + ), + ( + 'auth0|672659014296b7f94a9bab45' -- id_user_auth0 + , 'Tierney' -- firstname + , 'Gullen' -- surname + , 'tierneybailey13@gmail.com' -- email + , 1 -- is_super_user + , 1 -- active + ) ; # User Role link diff --git a/static/MySQL/0001_destroy.sql b/static/MySQL/0001_destroy.sql index b9a69b75..bf589c9a 100644 --- a/static/MySQL/0001_destroy.sql +++ b/static/MySQL/0001_destroy.sql @@ -117,6 +117,7 @@ DROP TABLE IF EXISTS Shop_User_Address; DROP TABLE IF EXISTS Shop_User_Role_Link_Audit; DROP TABLE IF EXISTS Shop_User_Role_Link; +DROP TABLE IF EXISTS Shop_User_Temp; DROP TABLE IF EXISTS Shop_User_Audit; DROP TABLE IF EXISTS Shop_User; diff --git a/static/MySQL/1312_tbl_Shop_User.sql b/static/MySQL/1312_tbl_Shop_User.sql index 629ac72c..7a10e89a 100644 --- a/static/MySQL/1312_tbl_Shop_User.sql +++ b/static/MySQL/1312_tbl_Shop_User.sql @@ -8,9 +8,9 @@ SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning CREATE TABLE IF NOT EXISTS Shop_User ( id_user INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id_user_auth0 VARCHAR(200) NOT NULL, - firstname VARCHAR(255) NOT NULL, - surname VARCHAR(255) NOT NULL, - email VARCHAR(254) NOT NULL, + firstname VARCHAR(255) NULL, + surname VARCHAR(255) NULL, + email VARCHAR(254) NULL, is_email_verified BIT NOT NULL DEFAULT 0, is_super_user BIT NOT NULL DEFAULT 0, id_currency_default INT NULL, diff --git a/static/MySQL/1314_tbl_Shop_User_Temp.sql b/static/MySQL/1314_tbl_Shop_User_Temp.sql new file mode 100644 index 00000000..b9728a76 --- /dev/null +++ b/static/MySQL/1314_tbl_Shop_User_Temp.sql @@ -0,0 +1,22 @@ + +# Users Temp + +-- DROP TABLE IF EXISTS Shop_User_Temp; + +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_User_Temp'; + +CREATE TABLE IF NOT EXISTS Shop_User_Temp ( + id_temp INT NOT NULL AUTO_INCREMENT PRIMARY KEY + , id_user INT NOT NULL + , id_user_auth0 VARCHAR(200) NOT NULL + , firstname VARCHAR(255) + , surname VARCHAR(255) + , email VARCHAR(254) + , is_email_verified BIT + , is_super_user BIT + , id_currency_default INT + , id_region_default INT + , is_included_VAT_default BIT + , active BIT + , guid BINARY(36) NOT NULL +); diff --git a/static/MySQL/7200_p_shop_save_product_category.sql b/static/MySQL/7200_p_shop_save_product_category.sql index e98199dc..1a00e9c5 100644 --- a/static/MySQL/7200_p_shop_save_product_category.sql +++ b/static/MySQL/7200_p_shop_save_product_category.sql @@ -24,19 +24,14 @@ BEGIN DECLARE exit handler for SQLEXCEPTION BEGIN - -- Get diagnostic information GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE , @errno = MYSQL_ERRNO , @text = MESSAGE_TEXT ; - -- Rollback the transaction ROLLBACK; - -- Select the error information - -- SELECT 'Error' AS status, @errno AS error_code, @sqlstate AS sql_state, @text AS message; - CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT , id_type INT NULL @@ -131,7 +126,7 @@ BEGIN SELECT v_id_type_error_bad_data , v_code_type_error_bad_data - , CONCAT('The following category(s) do not have a code: ', GROUP_CONCAT(IFNULL(t_C.name_error, 'NULL') SEPARATOR ', ')) AS msg + , CONCAT('The following category(s) do not have a code: ', GROUP_CONCAT(t_C.name_error SEPARATOR ', ')) AS msg FROM tmp_Category t_C WHERE ISNULL(t_C.code) ; @@ -146,7 +141,7 @@ BEGIN SELECT v_id_type_error_bad_data , v_code_type_error_bad_data - , CONCAT('The following category(s) do not have a name: ', GROUP_CONCAT(IFNULL(t_C.name_error, 'NULL') SEPARATOR ', ')) AS msg + , CONCAT('The following category(s) do not have a name: ', GROUP_CONCAT(t_C.name_error SEPARATOR ', ')) AS msg FROM tmp_Category t_C WHERE ISNULL(t_C.name) ; @@ -161,7 +156,7 @@ BEGIN SELECT v_id_type_error_bad_data , v_code_type_error_bad_data - , CONCAT('The following category(s) do not have a display order: ', GROUP_CONCAT(IFNULL(t_C.name_error, 'NULL') SEPARATOR ', ')) AS msg + , CONCAT('The following category(s) do not have a display order: ', GROUP_CONCAT(t_C.name_error SEPARATOR ', ')) AS msg FROM tmp_Category t_C WHERE ISNULL(t_C.display_order) ; diff --git a/static/MySQL/7203_p_shop_save_product.sql b/static/MySQL/7203_p_shop_save_product.sql index 3f9d1dfd..30693e1c 100644 --- a/static/MySQL/7203_p_shop_save_product.sql +++ b/static/MySQL/7203_p_shop_save_product.sql @@ -266,6 +266,7 @@ BEGIN , P.has_variations = t_P.has_variations , P.id_access_level_required = t_P.id_access_level_required , P.display_order = t_P.display_order + , P.active = t_P.active , P.id_change_set = v_id_change_set ; END IF; diff --git a/static/MySQL/7206_p_shop_save_product_permutation.sql b/static/MySQL/7206_p_shop_save_product_permutation.sql index 37c58cb2..82dc3414 100644 --- a/static/MySQL/7206_p_shop_save_product_permutation.sql +++ b/static/MySQL/7206_p_shop_save_product_permutation.sql @@ -536,7 +536,9 @@ BEGIN ; UPDATE Shop_Product_Permutation PP - INNER JOIN tmp_Permutation t_P ON PP.id_permutation = t_P.id_permutation + INNER JOIN tmp_Permutation t_P + ON PP.id_permutation = t_P.id_permutation + AND t_P.is_new = 0 SET PP.id_product = t_P.id_product , PP.description = t_P.description diff --git a/static/MySQL/7312_p_shop_save_user.sql b/static/MySQL/7312_p_shop_save_user.sql index fe964f7b..18d2c707 100644 --- a/static/MySQL/7312_p_shop_save_user.sql +++ b/static/MySQL/7312_p_shop_save_user.sql @@ -1,180 +1,275 @@ - - -/* - -CALL p_shop_edit_user ( - 'auth0|6582b95c895d09a70ba10fef', # a_id_user - '', # a_name - '', # a_email - 0 # a_email_verified -) - -*/ - - --- Clear previous proc -DROP PROCEDURE IF EXISTS p_shop_edit_user; + +DROP PROCEDURE IF EXISTS p_shop_save_user; DELIMITER // -CREATE PROCEDURE p_shop_edit_user ( - IN a_id_user INT, - IN a_name VARCHAR(255), - IN a_email VARCHAR(254), - IN a_email_verified BIT +CREATE PROCEDURE p_shop_save_user ( + IN a_comment VARCHAR(500), + IN a_guid BINARY(36), + IN a_id_user INT, + IN a_debug BIT ) BEGIN - -- Argument redeclaration - -- Variable declaration - DECLARE v_has_filter_user BIT; - -- DECLARE v_now DATETIME; + DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_id_permission_product INT; + DECLARE v_id_permission_user_admin LONGTEXT; + DECLARE v_id_change_set INT; + DECLARE v_id_access_level_edit INT; + DECLARE v_can_admin_user BIT; + DECLARE v_time_start TIMESTAMP(6); + DECLARE exit handler for SQLEXCEPTION + BEGIN + GET DIAGNOSTICS CONDITION 1 + @sqlstate = RETURNED_SQLSTATE + , @errno = MYSQL_ERRNO + , @text = MESSAGE_TEXT + ; + + ROLLBACK; + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + MET.id_type + , @errno + , @text + FROM partsltd_prod.Shop_Msg_Error_Type MET + WHERE MET.code = 'MYSQL_ERROR' + ; + SELECT * + FROM tmp_Msg_Error; + DROP TABLE IF EXISTS tmp_Msg_Error; + END; - -- Argument validation + default values - IF a_id_user IS NULL THEN - SET a_id_user = ''; - ELSE - SET a_id_user = TRIM(a_id_user); - END IF; - IF a_name IS NULL THEN - SET a_name = ''; - ELSE - SET a_name = TRIM(a_name); - END IF; - IF a_email IS NULL THEN - SET a_email = ''; - ELSE - SET a_email = TRIM(a_email); - END IF; - IF a_email_verified IS NULL THEN - SET a_email_verified = 0; - END IF; + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_id_type_error_bad_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_type_error_bad_data LIMIT 1); + SET v_id_access_level_edit := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'EDIT' LIMIT 1); + SET v_id_permission_user_admin := (SELECT GROUP_CONCAT(id_permission SEPARATOR ',') FROM Shop_Permission WHERE code = 'STORE_USER_ADMIN' LIMIT 1); + CALL p_validate_guid ( a_guid ); - -- Temporary tables DROP TABLE IF EXISTS tmp_Msg_Error; - DROP TABLE IF EXISTS tmp_Shop_User; + DROP TABLE IF EXISTS tmp_User; - CREATE TABLE tmp_Shop_User ( - id_user INT NOT NULL, - CONSTRAINT FK_tmp_Shop_User_id_user - FOREIGN KEY (id_user) - REFERENCES Shop_User(id_user), - active BIT NOT NULL + CREATE TABLE tmp_User ( + id_user INT NOT NULL + , id_user_auth0 VARCHAR(200) NOT NULL + , firstname VARCHAR(255) + , surname VARCHAR(255) + , email VARCHAR(254) + , is_email_verified BIT NOT NULL + , is_super_user BIT NOT NULL + , id_currency_default INT + , id_region_default INT + , is_included_VAT_default BIT + , active BIT NOT NULL + , name_error VARCHAR(1000) ); CREATE TABLE tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, id_type INT NOT NULL, - # code VARCHAR(50) NOT NULL, - # CONSTRAINT chk_tmp_Msg_Error_code CHECK (code IN (SELECT code FROM Shop_Msg_Error_Type)), - CONSTRAINT FK_tmp_Msg_Error_id_type - FOREIGN KEY (id_type) - REFERENCES Shop_Msg_Error_Type(id_type), + code VARCHAR(50) NOT NULL, msg VARCHAR(4000) NOT NULL ); - - -- Parse filters - SET v_has_filter_user = CASE WHEN a_id_user = '' THEN 0 ELSE 1 END; - - - -- User - IF v_has_filter_user THEN - INSERT INTO tmp_Shop_User ( - id_user, - active - ) - SELECT id_user, - active - FROM Shop_User - WHERE id_user LIKE CONCAT('%', a_id_user, '%') - AND active - LIMIT 1 - ; - - IF NOT EXISTS (SELECT id_user FROM tmp_Shop_User LIMIT 1) THEN - INSERT INTO Shop_User ( - id_user, - name, - email, - email_verified - ) - VALUES ( - a_id_user, - a_name, - a_email, - a_email_verified - ); - - INSERT INTO tmp_Shop_User ( - id_user, - active - ) - SELECT id_user, - active - FROM Shop_User - WHERE id_user LIKE CONCAT('%', a_id_user, '%') - AND active - LIMIT 1 - ; - END IF; - - SET a_id_user := (SELECT id_user FROM tmp_Shop_User LIMIT 1); - ELSE - INSERT INTO tmp_Msg_Error ( - id_type, - msg - ) - VALUES ( - (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1), - 'No user ID provided.' - ) - ; - END IF; - - - /* - IF NOT EXISTS (SELECT msg FROM tmp_Msg_Error LIMIT 1) THEN - END IF; - */ - - - -- Returns - # User - SELECT * - FROM tmp_Shop_User + -- Get data from Temp table + INSERT INTO tmp_User ( + id_user + , id_user_auth0 + , firstname + , surname + , email + , is_email_verified + , is_super_user + , id_currency_default + , id_region_default + , is_included_VAT_default + , active + ) + SELECT + U_T.id_user + , U_T.id_user_auth0 + , IFNULL(U_T.firstname, U.firstname) AS firstname + , IFNULL(U_T.surname, U.surname) AS surname + , IFNULL(U_T.email, U.email) AS email + , IFNULL(U_T.is_email_verified, U.is_email_verified) AS is_email_verified + , IFNULL(U_T.is_super_user, U.is_super_user) AS is_super_user + , IFNULL(U_T.id_currency_default, U.id_currency_default) AS id_currency_default + , IFNULL(U_T.id_region_default, U.id_region_default) AS id_region_default + , IFNULL(U_T.is_included_VAT_default, U.is_included_VAT_default) AS is_included_VAT_default + , IFNULL(IFNULL(U_T.active, U.active), 1) AS active + , IFNULL(U_T.display_order, PC.display_order) AS display_order + FROM partsltd_prod.Shop_User_Temp U_T + LEFT JOIN Shop_User U ON U_T.id_user = U.id_user + WHERE U_T.guid = a_guid ; + + UPDATE tmp_User t_U + SET + t_U.name_error = IFNULL(t_U.email, t_U.id_user_auth0) + ; + + -- Validation + -- Missing mandatory fields + -- email + IF EXISTS (SELECT * FROM tmp_User t_U WHERE ISNULL(t_U.email) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following User(s) do not have an email: ', GROUP_CONCAT(t_U.name_error SEPARATOR ', ')) AS msg + FROM tmp_User t_U + WHERE ISNULL(t_U.email) + ; + END IF; + -- is_super_user + IF EXISTS (SELECT * FROM tmp_User t_U WHERE ISNULL(t_U.is_super_user) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following User(s) do not have an is super user field: ', GROUP_CONCAT(t_U.name_error SEPARATOR ', ')) AS msg + FROM tmp_User t_U + WHERE ISNULL(t_U.is_super_user) + ; + END IF; + -- is_email_verified + IF EXISTS (SELECT * FROM tmp_User t_U WHERE ISNULL(t_U.is_email_verified) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following User(s) do not have an is email verified: ', GROUP_CONCAT(t_U.name_error SEPARATOR ', ')) AS msg + FROM tmp_User t_U + WHERE ISNULL(t_U.is_email_verified) + ; + END IF; + + + -- Permissions + IF a_debug = 1 THEN + SELECT + a_guid -- GUID + , a_id_user -- ID User + , FALSE -- get inactive Users + , v_id_permission_user_admin -- IDs Permission + , v_id_access_level_edit -- ID Access Level + , NULL -- IDs Product + ; + END IF; + + CALL p_shop_calc_user( + a_guid -- GUID + , a_id_user -- ID User + , FALSE -- get inactive Users + , v_id_permission_user_admin -- IDs Permission + , v_id_access_level_edit -- ID Access Level + , NULL -- IDs Product + ); + + SET v_can_admin_user := ( + SELECT IFNULL(UE_T.can_edit, 0) = 1 + FROM partsltd_prod.Shop_User_Eval_Temp UE_T + WHERE + UE_T.GUID = a_guid + AND UE_T.id_user = a_id_user + AND UE_T.id_permission = v_id_permission_user_admin + ); + + IF (v_can_admin_user = 0 AND EXISTS ( + SELECT * + FROM tmp_User t_U + WHERE + t_U.id_user <> a_id_user + )) THEN + DELETE FROM tmp_Msg_Error; + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + VALUES ( + v_id_type_error_no_permission + , v_code_type_error_no_permission + , 'You do not have permission to edit other Users.' + ) + ; + END IF; + + CALL p_shop_clear_calc_user(a_guid); + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + START TRANSACTION; + + INSERT INTO Shop_User_Change_Set ( comment ) + VALUES ( a_comment ) + ; + + SET v_id_change_set := LAST_INSERT_ID(); + + UPDATE Shop_User U + INNER JOIN tmp_User t_U ON U.id_user = t_U.id_user + SET + U.id_user_auth0 = t_U.id_user_auth0 + , U.firstname = t_U.firstname + , U.surname = t_U.surname + , U.email = t_U.email + , U.is_email_verified = t_U.is_email_verified + , U.is_super_user = t_U.is_super_user + , U.id_currency_default = t_U.id_currency_default + , U.id_region_default = t_U.id_region_default + , U.is_included_VAT_default = t_U.is_included_VAT_default + , U.active = t_U.active + , U.id_change_set = v_id_change_set + ; + + DELETE FROM Shop_User_Temp + WHERE GUID = a_guid; + + COMMIT; + END IF; # Errors SELECT * - FROM tmp_Msg_Error - ; + FROM tmp_Msg_Error t_ME + INNER JOIN partsltd_prod.Shop_Msg_Error_Type MET ON t_ME.id_type = MET.id_type + ; - /* - # Return arguments for test - SELECT a_id_user, - a_name, - a_email, - a_email_verified - ; - */ - - -- Clean up + IF a_debug = 1 THEN + SELECT * from tmp_User; + END IF; + DROP TABLE IF EXISTS tmp_Msg_Error; - DROP TABLE IF EXISTS tmp_Shop_User; + DROP TABLE IF EXISTS tmp_User; + + IF a_debug = 1 THEN + CALL partsltd_prod.p_debug_timing_reporting ( v_time_start ); + END IF; END // DELIMITER ;; - - -/* - -CALL p_shop_edit_user ( - '', - '', - '', - 0 -) - -*/ diff --git a/static/MySQL/7313_p_get_many_user.sql b/static/MySQL/7313_p_get_many_user.sql index 165f31d3..61d10ba1 100644 --- a/static/MySQL/7313_p_get_many_user.sql +++ b/static/MySQL/7313_p_get_many_user.sql @@ -10,7 +10,6 @@ CREATE PROCEDURE p_get_many_user ( , IN a_id_user_auth0 VARCHAR(200) , IN a_get_all_user BIT , IN a_get_inactive_user BIT - , IN a_get_first_user_only BIT , IN a_ids_user LONGTEXT , IN a_ids_user_auth0 LONGTEXT , IN a_debug BIT @@ -22,7 +21,6 @@ BEGIN DECLARE v_id_permission_user INT; DECLARE v_id_permission_user_admin INT; DECLARE v_ids_permission_required VARCHAR(4000); - DECLARE v_now DATETIME; DECLARE v_id_minimum INT; DECLARE v_code_error_bad_data VARCHAR(50); DECLARE v_id_type_error_bad_data INT; @@ -31,6 +29,7 @@ BEGIN DECLARE v_guid BINARY(36); DECLARE v_rank_max INT; DECLARE v_time_start TIMESTAMP(6); + DECLARE v_is_new BIT; SET v_time_start := CURRENT_TIMESTAMP(6); SET v_guid := UUID(); @@ -42,10 +41,11 @@ BEGIN SET v_code_error_bad_data := (SELECT code FROM partsltd_prod.Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); SET v_id_type_error_bad_data := (SELECT id_type FROM partsltd_prod.Shop_Msg_Error_Type WHERE code = v_code_error_bad_data LIMIT 1); SET v_ids_permission_required := CONCAT(v_id_permission_user, ',', v_id_permission_user_admin, ',', v_id_permission_store_admin); + SET v_is_new := FALSE; SET a_get_all_user := IFNULL(a_get_all_user, 1); SET a_get_inactive_user := IFNULL(a_get_inactive_user, 0); - SET a_get_first_user_only := IFNULL(a_get_first_user_only, 0); + -- SET a_get_first_user_only := IFNULL(a_get_first_user_only, 0); SET a_ids_user := TRIM(IFNULL(a_ids_user, '')); SET a_ids_user_auth0 := TRIM(IFNULL(a_ids_user_auth0, '')); SET a_debug := IFNULL(a_debug, 0); @@ -56,7 +56,7 @@ BEGIN , a_id_user_auth0 , a_get_all_user , a_get_inactive_user - , a_get_first_user_only + -- , a_get_first_user_only , a_ids_user , a_ids_user_auth0 , a_debug @@ -91,17 +91,33 @@ BEGIN END IF; IF ISNULL(a_id_user) THEN - INSERT INTO tmp_Msg_Error ( - id_type, - code, - msg - ) - VALUES ( - v_id_type_error_bad_data, - v_code_error_bad_data, - CONCAT('User ID required for authorisation.') - ) - ; + IF NOT ISNULL(a_id_user_auth0) THEN + INSERT INTO partsltd_prod.Shop_User ( + id_user_auth0 + , is_super_user + , active + ) + VALUES ( + a_id_user_auth0 + , 0 -- is_super_user + , 1 -- active + ) + ; + SET a_id_user := (SELECT U.id_user FROM partsltd_prod.Shop_User U WHERE U.id_user_auth0 = a_id_user_auth0 LIMIT 1); + SET v_is_new := TRUE; + ELSE + INSERT INTO tmp_Msg_Error ( + id_type, + code, + msg + ) + VALUES ( + v_id_type_error_bad_data, + v_code_error_bad_data, + CONCAT('User ID required for authorisation.') + ) + ; + END IF; END IF; SET v_has_filter_user := CASE WHEN a_ids_user = '' THEN 0 ELSE 1 END; @@ -268,6 +284,7 @@ BEGIN SELECT * FROM tmp_User; END IF; + /* IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN IF a_get_first_user_only THEN DELETE t_U @@ -276,6 +293,7 @@ BEGIN ; END IF; END IF; + */ IF a_debug = 1 THEN SELECT * FROM tmp_User; @@ -440,6 +458,7 @@ BEGIN , U.is_super_user , t_U.can_admin_store , t_U.can_admin_user + , v_is_new AS is_new FROM tmp_User t_U INNER JOIN partsltd_prod.Shop_User U ON t_U.id_user = U.id_user ; @@ -478,13 +497,22 @@ DELIMITER ;; -CALL p_get_many_user (NULL, 'google-oauth2|109567376920138999933', False, False, False, NULL, 'google-oauth2|109567376920138999933', 0); /* +CALL p_get_many_user ( + NULL + , 'google-oauth2|109567376920138999933' + , False + , False + -- , False + , NULL + , 'google-oauth2|109567376920138999933' + , 0 +); NULL # a_id_user , 'auth0|6582b95c895d09a70ba10fef' # a_id_user_auth0 , 0 # a_get_all_user , 0 # a_get_inactive_user - , 0 # a_get_first_user_only + -- , 0 # a_get_first_user_only , NULL # a_ids_user , 'auth0|6582b95c895d09a70ba10fef' # a_ids_user_auth0 , 0 -- a_debug @@ -502,7 +530,7 @@ CALL p_get_many_user( , 'auth0|6582b95c895d09a70ba10fef' -- :a_id_user_auth0, , 1 -- :a_get_all_user, , 0 -- :a_get_inactive_user, - , 0 -- :a_get_first_user_only, + -- , 0 -- :a_get_first_user_only, , NULL -- :a_ids_user, , 'auth0|6582b95c895d09a70ba10fef' -- :a_ids_user_auth0 ); diff --git a/static/MySQL/9000_populate.sql b/static/MySQL/9000_populate.sql index ca962db8..e5f29ab0 100644 --- a/static/MySQL/9000_populate.sql +++ b/static/MySQL/9000_populate.sql @@ -875,8 +875,6 @@ INSERT INTO Shop_User ( , email , is_super_user , active - , created_by - , created_on ) VALUES ( @@ -886,8 +884,6 @@ VALUES , 'edward.middletonsmith@gmail.com' -- email , 1 -- is_super_user , 1 -- active - , 1 -- created_by - , current_timestamp() -- created_on ), ( 'parts_guest' -- id_user_auth0 @@ -896,19 +892,15 @@ VALUES , '' -- email , 0 -- is_super_user , 1 -- active - , 1 -- created_by - , current_timestamp() -- created_on ), ( - 'auth0|672659014296b7f94a9bab45' -- id_user_auth0 - , 'Tierney' -- firstname - , 'Gullen' -- surname - , 'tierneybailey13@gmail.com' -- email - , 1 -- is_super_user - , 1 -- active - , 1 -- created_by - , current_timestamp() -- created_on -) + 'auth0|672659014296b7f94a9bab45' -- id_user_auth0 + , 'Tierney' -- firstname + , 'Gullen' -- surname + , 'tierneybailey13@gmail.com' -- email + , 1 -- is_super_user + , 1 -- active + ) ; # User Role link diff --git a/templates/pages/user/_user.html b/templates/pages/user/_user.html index 9edff528..5b0f028c 100644 --- a/templates/pages/user/_user.html +++ b/templates/pages/user/_user.html @@ -1,32 +1,56 @@ - - {% extends 'layouts/layout.html' %} {% block page_body %} - - -
- {% set firstname = 'new user' if user.firstname is none else user.firstname %} -

Welcome, {{ firstname }}

- {% set block_id = 'button_get_in_touch' %} - {% include 'components/common/buttons/_buttons_save_cancel.html' %} + + + {% set user = model.users[0] %} +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + {% set currency = user.currency_default %} + {% include 'components/store/_preview_DDL_currency.html' %} +
+
+
+
+ +
+ {{ user.region_default.name }} +
+
+
+
+
+ + +
+
+
- + {% include 'components/common/temporary/_overlay_confirm.html' %} + {% include 'components/common/temporary/_overlay_error.html' %} - {% endblock %} \ No newline at end of file