Feat(SQL, UI): Redesign database with much more detailed command response quality analysis and created successfully loading Dog Command Links page

This commit is contained in:
2025-06-28 20:48:37 +01:00
parent ab50a81a0e
commit caeb13429a
245 changed files with 7244 additions and 2035 deletions

13
app.py
View File

@@ -17,11 +17,13 @@ Initializes the Flask application, sets the configuration based on the environme
# IMPORTS
# internal
from config import app_config, Config
from controllers.core.contact import routes_core_contact
from dog_training.controllers.dog.dog import routes_dog
from dog_training.controllers.dog.dog_command_link import routes_dog_dog_command_link
from controllers.core.home import routes_core_home
from controllers.legal.legal import routes_legal
from extensions import db, csrf, mail, oauth
from helpers.helper_app import Helper_App
from controllers.user.user import routes_user
from dog_training.extensions import db, csrf, mail, oauth
from dog_training.helpers.helper_app import Helper_App
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session
# from flask_appconfig import AppConfig
@@ -106,10 +108,13 @@ with app.app_context():
access_token_url = f'https://{app.config["DOMAIN_AUTH0"]}/oauth/token',
)
print(f"Registered clients: {list(oauth._clients.keys())}")
app.register_blueprint(routes_core_home)
app.register_blueprint(routes_core_contact)
app.register_blueprint(routes_dog)
app.register_blueprint(routes_dog_dog_command_link)
app.register_blueprint(routes_legal)
app.register_blueprint(routes_user)

View File

@@ -11,8 +11,8 @@ Abstract business object
"""
# internal
from extensions import db
import lib.argument_validation as av
from dog_training.extensions import db
import dog_training.lib.argument_validation as av
# external
from typing import ClassVar
from flask import jsonify

View File

@@ -11,8 +11,8 @@ Abstract base class for all business objects in app
"""
# internal
from extensions import db
import lib.argument_validation as av
from dog_training.extensions import db
import dog_training.lib.argument_validation as av
# external
from typing import ClassVar

View File

@@ -11,9 +11,9 @@ Abstract base class for database objects
"""
# internal
# from helpers.DEPRECATED.helper_abc import Interface_ABC
from extensions import db
import lib.argument_validation as av
# from dog_training.helpers.DEPRECATED.helper_abc import Interface_ABC
from dog_training.extensions import db
import dog_training.lib.argument_validation as av
# external
from typing import ClassVar
from abc import abstractmethod, ABCMeta
@@ -45,4 +45,21 @@ class SQLAlchemy_ABC(db.Model, metaclass=SQLAlchemy_ABCMeta):
column.name: getattr(self, column.name)
for column in self.__table__.columns
if column.name not in excluded_attributes
}
}
class Get_Many_Parameters_Base(BaseModel, metaclass=ABCMeta):
# a_id_user: int
def __init__(self, **kwargs): # , a_id_user
super().__init__(**kwargs) # a_id_user=a_id_user,
@classmethod
@abstractmethod
def get_default(cls): # , id_user
pass
@classmethod
@abstractmethod
def from_json(self):
pass
@abstractmethod
def to_json(self):
pass # return self.dict()

View File

@@ -11,10 +11,10 @@ Business object for product
"""
# internal
import lib.argument_validation as av
from business_objects.base import Base
from extensions import db
from helpers.helper_app import Helper_App
import dog_training.lib.argument_validation as av
from dog_training.business_objects.base import Base
from dog_training.extensions import db
from dog_training.helpers.helper_app import Helper_App
# external
from pydantic import BaseModel
from typing import ClassVar
@@ -23,7 +23,7 @@ from typing import ClassVar
class Access_Level(db.Model, Base):
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_ACCESS_LEVEL
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME
__tablename__ = 'PH_Access_Level_Temp'
__tablename__ = 'DOG_Access_Level_Temp'
id_access_level = db.Column(db.Integer, primary_key=True)
code = db.Column(db.String(50))
name = db.Column(db.String(250))

View File

@@ -0,0 +1,136 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Dog Command Link Container Business Object
Description:
Business object for dog command link container
DEPRECATED AS NOT REQUIRED - USE A LIST
"""
# internal
import dog_training.lib.argument_validation as av
from dog_training.business_objects.base import Base
from dog_training.business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
from dog_training.business_objects.dog.dog_command_link import Dog_Command_Link
from dog_training.extensions import db
from dog_training.helpers.helper_app import Helper_App
# external
from pydantic import BaseModel
from typing import ClassVar
class Dog_Command_Link_Container(Base):
NAME_ATTR_OPTION_TEXT: ClassVar[str] = ''
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.FLAG_ROWS
categories: list
def __init__(self):
self.categories = []
def add_dog_command_link(self, dog_command_link):
av.val_instance(dog_command_link, 'dog_command_link', 'Dog_Command_Link_Container.add_dog_command_link', Dog_Command_Link)
self.categories.append(dog_command_link)
def get_index_category_from_id(self, id_category):
for index_category in range(len(self.categories)):
category = self.categories[index_category]
if category.id_category == id_category:
return index_category
raise ValueError(f"{av.error_msg_str(id_category, 'id_category', 'Dog_Command_Link_Container.get_index_category_from_id', int)}\nID not in list")
def get_index_category_from_id_permutation(self, id_permutation):
for index_category in range(len(self.categories)):
category = self.categories[index_category]
try:
index_product = category.get_index_product_from_id_permutation(id_permutation)
return index_category
except:
pass
raise ValueError(f"{av.error_msg_str(id_permutation, 'id_permutation', 'Dog_Command_Link_Container.get_index_category_from_id_permutation', int)}. Permutation ID not in list")
def add_product(self, product):
av.val_instance(product, 'product', 'Dog_Command_Link_Container.add_product', Product)
index_category = self.get_index_category_from_id(product.id_category)
self.categories[index_category].add_product(product)
def add_product_permutation(self, permutation):
av.val_instance(permutation, 'permutation', 'Dog_Command_Link_Container.add_product_permutation', Product_Permutation)
index_category = self.get_index_category_from_id(permutation.id_category)
self.categories[index_category].add_product_permutation(permutation)
def add_product_variation_type(self, variation_type):
av.val_instance(variation_type, 'variation_type', 'Dog_Command_Link_Container.add_product_variation_type', Product_Variation_Type)
variation = variation_type.variations[0]
index_category = self.get_index_category_from_id(variation.id_category)
self.categories[index_category].add_product_variation_type(variation_type)
def add_product_price(self, price):
av.val_instance(price, 'price', 'Dog_Command_Link_Container.add_product_price', Product_Price)
index_category = self.get_index_category_from_id(price.id_category)
self.categories[index_category].add_product_price(price)
def add_product_image(self, image):
av.val_instance(image, 'image', 'Dog_Command_Link_Container.add_product_image', Image)
index_category = self.get_index_category_from_id(image.id_category)
self.categories[index_category].add_product_image(image)
def add_delivery_option(self, delivery_option):
av.val_instance(delivery_option, 'delivery_option', 'Dog_Command_Link_Container.add_delivery_option', Delivery_Option)
index_category = self.get_index_category_from_id(delivery_option.id_category)
self.categories[index_category].add_delivery_option(delivery_option)
def add_product_price_discount(self, discount):
av.val_instance(discount, 'discount', 'Dog_Command_Link_Container.add_product_price_discount', Discount)
index_category = self.get_index_category_from_id(discount.id_category)
self.categories[index_category].add_product_price_discount(discount)
def add_stock_item(self, stock_item):
av.val_instance(stock_item, 'stock_item', 'Dog_Command_Link_Container.add_stock_item', Stock_Item)
index_category = self.get_index_category_from_id(stock_item.id_category)
self.categories[index_category].add_stock_item(stock_item)
def get_all_product_variation_trees(self):
for category in self.categories:
category.get_all_product_variation_trees()
def __repr__(self):
return f'categories: {self.categories}'
def get_category_count(self):
return len(self.categories)
def to_permutation_row_list(self):
list_rows = []
for category in self.categories:
list_rows += category.to_permutation_row_list()
return list_rows
def to_category_option_list(self):
list_categories = []
for category in self.categories:
list_categories.append({'value': category.id_category, 'text': category.name})
return list_categories
def get_list_products(self):
list_products = []
for category in self.categories:
list_products += category.products
return list_products
def to_product_option_list(self):
list_products = self.get_list_products()
return [{'value': product.id_product, 'text': product.name, Product.ATTR_ID_Dog_Command_Link: product.id_category} for product in list_products]
def get_product_option_lists_by_category(self):
dict_lists_products = {}
for category in self.categories:
dict_lists_products[category.id_category] = category.to_product_option_list()
return dict_lists_products
def to_json(self):
return {
**self.get_shared_json_attributes(self),
f'{self.FLAG_ROWS}': [category.to_json() for category in self.categories]
}
@classmethod
def from_json(cls, json):
return None
def to_json_option(self):
return None
def to_temporary_record(self):
excluded_attributes = {
column.name: getattr(self, column.name)
for column in self.__table__.columns
if column.name not in ['created_on', 'created_by']
}
return self.to_object_with_missing_attributes(excluded_attributes)
def get_csv_ids_permutation(self):
list_ids = []
for category in self.categories:
list_ids += category.get_csv_ids_permutation()
return ','.join(list_ids)

View File

@@ -8,11 +8,11 @@ Feature: Understanding Level Business Object
"""
# internal
from business_objects.base import Base
from business_objects.db_base import SQLAlchemy_ABC
import lib.argument_validation as av
from extensions import db
from helpers.helper_app import Helper_App
from dog_training.business_objects.base import Base
from dog_training.business_objects.db_base import SQLAlchemy_ABC
import dog_training.lib.argument_validation as av
from dog_training.extensions import db
from dog_training.helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar
@@ -36,8 +36,8 @@ class Understanding_Level(SQLAlchemy_ABC, Base):
self.is_new = False
super().__init__()
def from_DB_Dog_Understanding_Level(query_row):
_m = 'Understanding_Level.from_DB_Dog_Understanding_Level'
def from_db_dog_command_link(query_row):
_m = 'Understanding_Level.from_db_dog_command_link'
level = Understanding_Level()
level.id_understanding_level = query_row[5]
level.code = query_row[6]

View File

@@ -8,18 +8,19 @@ Feature: Command Business Object
"""
# internal
from business_objects.base import Base
from business_objects.dog.command_category import Command_Category
from business_objects.db_base import SQLAlchemy_ABC
import lib.argument_validation as av
from extensions import db
from helpers.helper_app import Helper_App
from dog_training.business_objects.base import Base
from dog_training.business_objects.dog.command_category import Command_Category
from dog_training.business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
import dog_training.lib.argument_validation as av
from dog_training.extensions import db
from dog_training.helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar
class Command(SQLAlchemy_ABC, Base):
ATTR_ID_COMMAND: ClassVar[str] = 'id_command'
FLAG_COMMAND: ClassVar[str] = 'command'
FLAG_HAND_SIGNAL_DEFAULT_DESCRIPTION: ClassVar[str] = 'hand-signal-default-description'
FLAG_CAN_HAVE_BUTTON: ClassVar[str] = 'can-have-button'
@@ -44,12 +45,26 @@ class Command(SQLAlchemy_ABC, Base):
self.has_button = False
super().__init__()
def from_DB_Dog_Command(query_row):
_m = 'Command.from_DB_Dog_Command'
def from_db_command(query_row):
_m = 'Command.from_db_command'
command = Command()
command.id_command = query_row[0]
command.id_command_category = query_row[1]
command.name = query_row[2]
command.hand_signal_default_description = query_row[3]
command.can_have_button = av.input_bool(query_row[4], 'can_have_button', _m)
# command.has_button = av.input_bool(query_row[7], 'has_button', _m)
command.notes = query_row[5]
command.active = av.input_bool(query_row[6], 'active', _m)
# command.created_on = query_row[7]
return command
def from_db_dog_command_link(query_row):
_m = 'Command.from_db_dog_command_link'
command = Command()
command.id_command = query_row[5]
command.id_command_category = query_row[3]
command.name = query_row[7]
command.name = query_row[6]
# command.hand_signal_default_description = query_row[2]
# command.can_have_button = av.input_bool(query_row[5], 'can_have_button', _m)
command.has_button = av.input_bool(query_row[7], 'has_button', _m)
@@ -132,4 +147,52 @@ class Command_Temp(db.Model, Base):
temp.notes = command.notes
temp.active = command.active
temp.created_on = command.created_on
return temp
return temp
class Parameters_Command(Get_Many_Parameters_Base):
get_all_command: bool
get_inactive_command: bool
ids_command: str
names_command: str
@classmethod
def get_default(cls):
return cls(
get_all_command = True
, get_inactive_command = False
, ids_command = ''
, names_command = ''
)
@classmethod
def from_json(cls, json):
return cls(
get_all_command = json.get('a_get_all_command', False)
, get_inactive_command = json.get('a_get_inactive_command', False)
, ids_command = json.get('a_ids_command', '')
, names_command = json.get('a_names_command', '')
)
"""
@classmethod
def from_form_filters_command(cls, form):
av.val_instance(form, 'form', 'Parameters_Command.from_form_filters_command', Filters_Command)
has_filter_command = not (form.id_command.data == '0' or form.id_command.data == '' or form.id_command.data is None)
active_only = av.input_bool(form.active.data, "active", "Parameters_Command.from_form_filters_command")
return cls(
get_all_command = not has_filter_command
, get_inactive_command = not active_only
, ids_command = form.id_command.data if has_filter_id else ''
, names_command = form.name_command.data if has_filter_name else ''
)
"""
def to_json(self):
return {
'a_get_all_command': self.get_all_command
, 'a_get_inactive_command': self.get_inactive_command
, 'a_ids_command': self.ids_command
, 'a_names_command': self.names_command
}

View File

@@ -8,11 +8,11 @@ Feature: Command Category Business Object
"""
# internal
from business_objects.base import Base
from business_objects.db_base import SQLAlchemy_ABC
import lib.argument_validation as av
from extensions import db
from helpers.helper_app import Helper_App
from dog_training.business_objects.base import Base
from dog_training.business_objects.db_base import SQLAlchemy_ABC
import dog_training.lib.argument_validation as av
from dog_training.extensions import db
from dog_training.helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar
@@ -36,12 +36,12 @@ class Command_Category(SQLAlchemy_ABC, Base):
self.is_new = False
super().__init__()
def from_DB_Dog_Command(query_row):
_m = 'Command_Category.from_DB_Dog_Command'
def from_db_dog_command_link(query_row):
_m = 'Command_Category.from_db_dog_command_link'
level = Command_Category()
level.id_command_category = query_row[5]
level.code = query_row[6]
level.name = query_row[7]
level.id_command_category = query_row[3]
# level.code = query_row[6]
level.name = query_row[4]
level.active = True
return level

View File

@@ -8,17 +8,18 @@ Feature: Dog Business Object
"""
# internal
from business_objects.base import Base
from business_objects.db_base import SQLAlchemy_ABC
import lib.argument_validation as av
from extensions import db
from helpers.helper_app import Helper_App
from dog_training.business_objects.base import Base
from dog_training.business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
import dog_training.lib.argument_validation as av
from dog_training.extensions import db
from dog_training.helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar
class Dog(SQLAlchemy_ABC, Base):
ATTR_ID_DOG: ClassVar[str] = 'id_dog'
FLAG_DOG: ClassVar[str] = 'dog'
FLAG_APPEARANCE: ClassVar[str] = 'appearance'
FLAG_MASS_KG: ClassVar[str] = 'mass-kg'
@@ -41,8 +42,19 @@ class Dog(SQLAlchemy_ABC, Base):
self.is_new = False
super().__init__()
def from_DB_Dog_Command(query_row):
_m = 'Dog.from_DB_Dog'
def from_db_dog(query_row):
_m = 'Dog.from_db_dog'
dog = Dog()
dog.id_dog = query_row[0]
dog.name = query_row[1]
dog.appearance = query_row[2]
dog.mass_kg = query_row[3]
dog.notes = query_row[4]
dog.active = av.input_bool(query_row[5], 'active', _m)
return dog
def from_db_dog_command_link(query_row):
_m = 'Dog.from_db_dog_command_link'
dog = Dog()
dog.id_dog = query_row[1]
dog.name = query_row[2]
@@ -122,3 +134,53 @@ class Dog_Temp(db.Model, Base):
temp.active = dog.active
temp.created_on = dog.created_on
return temp
class Parameters_Dog(Get_Many_Parameters_Base):
get_all_dog: bool
get_inactive_dog: bool
ids_dog: str
names_dog: str
@classmethod
def get_default(cls):
return cls(
get_all_dog = True
, get_inactive_dog = False
, ids_dog = ''
, names_dog = ''
)
@classmethod
def from_json(cls, json):
return cls(
get_all_dog = json.get('a_get_all_dog', False)
, get_inactive_dog = json.get('a_get_inactive_dog', False)
, ids_dog = json.get('a_ids_dog', '')
, names_dog = json.get('names_dog', '')
)
"""
@classmethod
def from_form_filters_dog(cls, form):
av.val_instance(form, 'form', 'Parameters_Dog.from_form_filters_dog', Filters_Dog)
has_filter_id = not (form.id_dog.data == '0' or form.id_dog.data == '' or form.id_dog.data is None)
has_filter_name = not (form.name_dog.data == '0' or form.name_dog.data == '' or form.name_dog.data is None)
has_filter_dog = has_filter_id or has_filter_name
active_only = av.input_bool(form.active.data, "active", "Parameters_Dog.from_form_filters_dog")
return cls(
get_all_dog = not has_filter_dog
, get_inactive_dog = not active_only
, ids_dog = form.id_dog.data if has_filter_id else ''
, names_dog = form.name_dog.data if has_filter_name else ''
)
"""
def to_json(self):
return {
'a_get_all_dog': self.get_all_dog
, 'a_get_inactive_dog': self.get_inactive_dog
, 'a_ids_dog': self.ids_dog
, 'a_names_dog': self.names_dog
}

View File

@@ -8,16 +8,16 @@ Feature: Dog Command Link Business Object
"""
# internal
from business_objects.base import Base
from business_objects.dog.command import Command
from business_objects.dog.command_category import Command_Category
from business_objects.db_base import SQLAlchemy_ABC
from business_objects.dog.dog import Dog
from business_objects.dog.obedience_level import Obedience_Level
from business_objects.dog.understanding_level import Understanding_Level
import lib.argument_validation as av
from extensions import db
from helpers.helper_app import Helper_App
from dog_training.business_objects.base import Base
from dog_training.business_objects.dog.command import Command
# from dog_training.business_objects.dog.command_category import Command_Category
from dog_training.business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
from dog_training.business_objects.dog.dog import Dog
from dog_training.business_objects.dog.obedience_level import Obedience_Level
from dog_training.extensions import db
from dog_training.forms.dog.dog_command_link import Filters_Dog_Command_Link
from dog_training.helpers.helper_app import Helper_App
import dog_training.lib.argument_validation as av
# external
from dataclasses import dataclass
from typing import ClassVar
@@ -26,42 +26,40 @@ from typing import ClassVar
class Dog_Command_Link(SQLAlchemy_ABC, Base):
FLAG_DOG_COMMAND_LINK: ClassVar[str] = 'dog_command_link'
FLAG_HAND_SIGNAL_DESCRIPTION: ClassVar[str] = 'hand-signal-description'
FLAG_CAN_HAVE_BUTTON: ClassVar[str] = 'can-have-button'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = FLAG_DOG_COMMAND_LINK
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME
__tablename__ = 'DOG_Dog_Command_Link'
__table_args__ = { 'extend_existing': True }
id_dog_command_link = db.Column(db.Integer, primary_key=True)
id_link = db.Column(db.Integer, primary_key=True)
id_dog = db.Column(db.Integer)
id_command = db.Column(db.Integer)
id_understanding_level = db.Column(db.Integer)
id_obedience_level = db.Column(db.Integer)
hand_signal_description = db.Column(db.Text)
notes = db.Column(db.Text)
active = db.Column(db.Boolean)
created_on = db.Column(db.DateTime)
def __init__(self):
self.id_dog_command_link = 0
self.id_link = 0
self.is_new = False
#self.id_command_category = None
self.dog = None
self.command = None
super().__init__()
def from_DB_Dog_Command(query_row):
_m = 'Dog_Command_Link.from_DB_Dog_Command'
def from_db_dog_command_link(query_row):
_m = 'Dog_Command_Link.from_db_dog_command_link'
dog_command_link = Dog_Command_Link()
dog_command_link.id_dog_command_link = query_row[0]
dog_command_link.id_link = query_row[0]
dog_command_link.id_dog = query_row[1]
#dog_command_link.id_command_category = query_row[3]
dog_command_link.id_command = query_row[5]
dog_command_link.id_understanding_level = query_row[8]
dog_command_link.id_obedience_level = query_row[11]
dog_command_link.hand_signal_description = query_row[14]
dog_command_link.notes = query_row[15]
dog_command_link.active = av.input_bool(query_row[16], 'active', _m)
dog_command_link.hand_signal_description = query_row[8]
dog_command_link.notes = query_row[9]
dog_command_link.active = av.input_bool(query_row[10], 'active', _m)
# dog_command_link.created_on = query_row[7]
dog_command_link.dog = Dog.from_db_dog_command_link(query_row)
dog_command_link.command = Command.from_db_dog_command_link(query_row)
return dog_command_link
@classmethod
@@ -70,11 +68,9 @@ class Dog_Command_Link(SQLAlchemy_ABC, Base):
dog_command_link = cls()
if json is None: return dog_command_link
Helper_App.console_log(f'{_m}\njson: {json}')
dog_command_link.id_dog_command_link = -1
dog_command_link.id_link = -1
dog_command_link.id_dog = json[Dog.FLAG_DOG]
dog_command_link.id_command = json[Command.FLAG_COMMAND]
dog_command_link.id_understanding_level = json[Understanding_Level.FLAG_UNDERSTANDING_LEVEL]
dog_command_link.id_obedience_level = json[Obedience_Level.FLAG_OBEDIENCE_LEVEL]
dog_command_link.hand_signal_description = json[cls.FLAG_HAND_SIGNAL_DESCRIPTION]
dog_command_link.notes = json[cls.FLAG_NOTES]
dog_command_link.active = json[cls.FLAG_ACTIVE]
@@ -85,11 +81,9 @@ class Dog_Command_Link(SQLAlchemy_ABC, Base):
def to_json(self):
as_json = {
self.FLAG_DOG_COMMAND_LINK: self.id_dog_command_link
self.FLAG_DOG_COMMAND_LINK: self.id_link
, Dog.FLAG_DOG: self.id_dog
, Command.FLAG_COMMAND: self.id_command
, Understanding_Level.FLAG_UNDERSTANDING_LEVEL: self.id_understanding_level
, Obedience_Level.FLAG_OBEDIENCE_LEVEL: self.id_obedience_level
, self.FLAG_HAND_SIGNAL_DESCRIPTION: self.hand_signal_description
, self.FLAG_NOTES: self.notes
, self.FLAG_ACTIVE: self.active
@@ -102,11 +96,9 @@ class Dog_Command_Link(SQLAlchemy_ABC, Base):
def __repr__(self):
return f'''
{self.__class__.__name__}(
{self.FLAG_DOG_COMMAND_LINK}: {self.id_dog_command_link}
{Dog.FLAG_DOG}: {self.id_dog}
{Command.FLAG_COMMAND}: {self.id_command}
{Understanding_Level.FLAG_UNDERSTANDING_LEVEL}: {self.id_understanding_level}
{Obedience_Level.FLAG_OBEDIENCE_LEVEL}: {self.id_obedience_level}
{self.FLAG_DOG_COMMAND_LINK}: {self.id_link}
{Dog.FLAG_DOG}: {self.dog}
{Command.FLAG_COMMAND}: {self.command}
{self.FLAG_HAND_SIGNAL_DESCRIPTION}: {self.hand_signal_description}
{self.FLAG_NOTES}: {self.notes}
{self.FLAG_ACTIVE}: {self.active}
@@ -119,11 +111,9 @@ class Dog_Command_Link_Temp(db.Model, Base):
__tablename__ = 'DOG_Dog_Command_Link_Temp'
__table_args__ = { 'extend_existing': True }
id_temp = db.Column(db.Integer, primary_key=True)
id_dog_command_link = db.Column(db.Integer)
id_link = db.Column(db.Integer)
id_dog = db.Column(db.Integer)
id_command = db.Column(db.Integer)
id_understanding_level = db.Column(db.Integer)
id_obedience_level = db.Column(db.Integer)
hand_signal_description = db.Column(db.Text)
notes = db.Column(db.Text)
active = db.Column(db.Boolean)
@@ -137,13 +127,68 @@ class Dog_Command_Link_Temp(db.Model, Base):
def from_Dog_Command_Link(cls, dog_command_link):
_m = 'Dog_Command_Link_Temp.from_Dog_Command_Link'
temp = cls()
temp.id_dog_command_link = dog_command_link.id_dog_command_link
temp.id_link = dog_command_link.id_link
temp.id_dog = dog_command_link.id_dog
temp.id_command = dog_command_link.id_command
temp.id_understanding_level = dog_command_link.id_understanding_level
temp.id_obedience_level = dog_command_link.id_obedience_level
temp.hand_signal_description = dog_command_link.hand_signal_description
temp.notes = dog_command_link.notes
temp.active = dog_command_link.active
temp.created_on = dog_command_link.created_on
return temp
return temp
class Parameters_Dog_Command_Link(Get_Many_Parameters_Base):
get_all_dog: bool
get_inactive_dog: bool
ids_dog: str
get_all_command: bool
get_inactive_command: bool
ids_command: str
@classmethod
def get_default(cls):
return cls(
get_all_dog = True
, get_inactive_dog = False
, ids_dog = ''
, get_all_command = True
, get_inactive_command = False
, ids_command = ''
)
@classmethod
def from_json(cls, json):
return cls(
get_all_dog = json.get('a_get_all_dog', False)
, get_inactive_dog = json.get('a_get_inactive_dog', False)
, ids_dog = json.get('a_ids_dog', '')
, get_all_command = json.get('a_get_all_command', False)
, get_inactive_command = json.get('a_get_inactive_command', False)
, ids_command = json.get('a_ids_command', '')
)
@classmethod
def from_form_filters_dog_command_link(cls, form):
av.val_instance(form, 'form', 'Parameters_Dog_Command_Link.from_form_filters_dog_command_link', Filters_Dog_Command_Link)
has_filter_dog = not (form.id_dog.data == '0' or form.id_dog.data == '' or form.id_dog.data is None)
has_filter_command = not (form.id_command.data == '0' or form.id_command.data == '' or form.id_command.data is None)
active_only = av.input_bool(form.active.data, "active", "Parameters_Dog_Command_Link.from_form_filters_dog_command_link")
return cls(
get_all_dog = not has_filter_dog
, get_inactive_dog = not active_only
, ids_dog = form.id_dog.data if has_filter_dog else ''
, get_all_command = not has_filter_command
, get_inactive_command = not active_only
, ids_command = form.id_command.data if has_filter_command else ''
)
def to_json(self):
return {
'a_get_all_dog': self.get_all_dog
, 'a_get_inactive_dog': self.get_inactive_dog
, 'a_ids_dog': self.ids_dog
, 'a_get_all_command': self.get_all_command
, 'a_get_inactive_command': self.get_inactive_command
, 'a_ids_command': self.ids_command
}

View File

@@ -8,11 +8,11 @@ Feature: Obedience Level Business Object
"""
# internal
from business_objects.base import Base
from business_objects.db_base import SQLAlchemy_ABC
import lib.argument_validation as av
from extensions import db
from helpers.helper_app import Helper_App
from dog_training.business_objects.base import Base
from dog_training.business_objects.db_base import SQLAlchemy_ABC
import dog_training.lib.argument_validation as av
from dog_training.extensions import db
from dog_training.helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar
@@ -35,16 +35,16 @@ class Obedience_Level(SQLAlchemy_ABC, Base):
self.id_obedience_level = 0
self.is_new = False
super().__init__()
def from_DB_Dog_Command(query_row):
_m = 'Obedience_Level.from_DB_Dog_Command'
"""
def from_db_dog_command_link(query_row):
_m = 'Obedience_Level.from_db_dog_command_link'
level = Obedience_Level()
level.id_obedience_level = query_row[5]
level.code = query_row[6]
level.name = query_row[7]
level.active = True
return level
"""
@classmethod
def from_json(cls, json):
_m = 'Obedience_Level.from_json'

View File

@@ -8,12 +8,12 @@ Feature: User Business Object
"""
# internal
from business_objects.base import Base
from business_objects.db_base import SQLAlchemy_ABC
import lib.argument_validation as av
from forms.forms import Form_Contact
from extensions import db
from helpers.helper_app import Helper_App
from dog_training.business_objects.base import Base
from dog_training.business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
import dog_training.lib.argument_validation as av
from dog_training.extensions import db
from dog_training.forms.base import Form_Filters_User
from dog_training.helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar
@@ -23,7 +23,7 @@ class User(SQLAlchemy_ABC, Base):
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_USER
NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'email'
__tablename__ = 'PH_User'
__tablename__ = 'DOG_User'
__table_args__ = { 'extend_existing': True }
id_user = db.Column(db.Integer, primary_key=True)
@@ -114,7 +114,7 @@ class User(SQLAlchemy_ABC, Base):
return (self.id_user > 0 and self.id_user != Base.ID_USER_GUEST)
class User_Temp(db.Model, Base):
__tablename__ = 'Shop_User_Temp'
__tablename__ = 'DOG_User_Temp'
__table_args__ = { 'extend_existing': True }
id_user = db.Column(db.Integer, primary_key=True)
id_user_auth0 = db.Column(db.String(250))
@@ -130,4 +130,100 @@ class User_Temp(db.Model, Base):
def __init__(self):
self.id_user = 0
super().__init__()
super().__init__()
class Parameters_User(Get_Many_Parameters_Base):
get_all_user: bool
get_inactive_user: bool
ids_user: str
ids_user_auth0: str
@staticmethod
def from_form(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 = '' if form.id_user.data is None else form.id_user.data
return Parameters_User(
get_all_user = (id_user == ''),
get_inactive_user = get_inactive,
ids_user = id_user,
ids_user_auth0 = '',
)
@staticmethod
def from_user(user):
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,
ids_user = '' if user.id_user is None else str(user.id_user),
ids_user_auth0 = user.id_user_auth0,
)
@staticmethod
def get_default():
return Parameters_User(
get_all_user = False,
get_inactive_user = False,
ids_user = '',
ids_user_auth0 = ''
)
@classmethod
def from_json(self):
pass
def to_json(self):
return {
'a_get_all_user': self.get_all_user
, 'a_get_inactive_user': self.get_inactive_user
, 'a_ids_user': self.ids_user
, 'a_ids_user_auth0': self.ids_user_auth0
}
class User_Permission_Evaluation(db.Model):
__tablename__ = 'DOG_User_Permission_Evaluation'
__table_args__ = { 'extend_existing': True }
id_evaluation = db.Column(db.Integer, primary_key=True)
guid = db.Column(db.String(255))
id_user = db.Column(db.Integer)
id_permission_required = db.Column(db.Integer)
priority_access_level_required = db.Column(db.Integer)
id_product = db.Column(db.Integer)
is_super_user = db.Column(db.Boolean)
priority_access_level_user = db.Column(db.Integer)
can_view = db.Column(db.Boolean)
can_edit = db.Column(db.Boolean)
can_admin = db.Column(db.Boolean)
def from_DB_user_eval(query_row):
user_permission_evaluation = User_Permission_Evaluation()
user_permission_evaluation.id_evaluation = query_row[0]
user_permission_evaluation.guid = query_row[1]
user_permission_evaluation.id_user = query_row[2]
user_permission_evaluation.id_permission_required = query_row[3]
user_permission_evaluation.priority_access_level_required = query_row[4]
user_permission_evaluation.id_product = query_row[5]
user_permission_evaluation.is_super_user = query_row[6]
user_permission_evaluation.priority_access_level_user = query_row[7]
user_permission_evaluation.can_view = query_row[8]
user_permission_evaluation.can_edit = query_row[9]
user_permission_evaluation.can_admin = query_row[10]
return user_permission_evaluation
def __repr__(self):
return f'''
id_evaluation: {self.id_evaluation}
guid: {self.guid}
id_user: {self.id_user}
id_permission_required: {self.id_permission_required}
priority_access_level_required: {self.priority_access_level_required}
id_product: {self.id_product}
is_super_user: {self.is_super_user}
priority_access_level_user: {self.priority_access_level_user}
can_view: {self.can_view}
can_edit: {self.can_edit}
can_admin: {self.can_admin}
'''

View File

@@ -11,10 +11,9 @@ Business object for SQL errors returned by Get Many Stored Procedures
"""
# internal
from business_objects.base import Base
import lib.argument_validation as av
from lib import data_types
from forms.forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
from dog_training.business_objects.base import Base
import dog_training.lib.argument_validation as av
from dog_training.lib import data_types
# external
from enum import Enum
from datetime import datetime, timedelta
@@ -49,7 +48,7 @@ class SQL_Error(db.Model):
super().__init__()
"""
def from_DB_record(record):
def from_db_record(record):
error = SQL_Error()
error.display_order = record[0]
error.id_type = record[1]

View File

@@ -37,9 +37,9 @@ class Config:
'pool_timeout': 30,
}
# Auth0
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = False
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Strict'
SESSION_COOKIE_SAMESITE = 'Lax'
REMEMBER_COOKIE_SECURE = True
WTF_CSRF_ENABLED = True
# WTF_CSRF_CHECK_DEFAULT = False # We'll check it manually for API routes

View File

@@ -1,143 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Core - Contact Routes
Description:
Contact Page Controller.
"""
# IMPORTS
# internal
from business_objects.api import API
from business_objects.project_hub.command import Command
from datastores.project_hub.datastore_command import DataStore_Command
from forms.contact import Form_Contact
from helpers.helper_app import Helper_App
from models.model_view_contact import Model_View_Contact
from models.model_view_contact_success import Model_View_Contact_Success
from models.model_view_home import Model_View_Home
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, flash
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
import json
import base64
import hmac
import hashlib
import datetime
from altcha import ChallengeOptions, create_challenge, verify_solution
routes_core_contact = Blueprint('routes_core_contact', __name__)
@routes_core_contact.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['GET'])
def contact():
try:
form = Form_Contact()
model = Model_View_Contact(form)
html_body = render_template('pages/core/_contact.html', model = model)
return html_body
except Exception as e:
return API.get_standard_response(
success = False,
status_code = 500,
message = f"Error: {e}",
data = None,
errors = [str(e)],
meta = None
)
@routes_core_contact.route(Model_View_Contact.HASH_GET_ALTCHA_CHALLENGE, methods=['GET'])
def create_altcha_challenge():
options = ChallengeOptions(
expires = datetime.datetime.now() + datetime.timedelta(hours=1),
max_number = 100000, # The maximum random number
hmac_key = current_app.app_config.ALTCHA_SECRET_KEY,
)
challenge = create_challenge(options)
Helper_App.console_log(f"Challenge created: {challenge}")
# return jsonify({"challenge": challenge})
return jsonify({
"algorithm": challenge.algorithm,
"challenge": challenge.challenge,
"salt": challenge.salt,
"signature": challenge.signature,
})
@routes_core_contact.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['POST'])
def contact_post():
try:
form = Form_Contact()
if form.validate_on_submit():
try:
email = form.email.data
# CC = form.CC.data # not in use
contact_name = form.contact_name.data
company_name = form.company_name.data
message = form.message.data
receive_marketing = form.receive_marketing.data
receive_marketing_text = "I would like to receive marketing emails.\n" if receive_marketing else ""
# 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{receive_marketing_text}\nKind regards,\n{contact_name}\n{company_name}\n{email}"
mail.send(mailItem)
# save to database
datastore = DataStore_Command()
command = Command.from_json(form.to_json())
datastore.save_commands(
comment = command.message
, commands = [command]
)
return redirect(url_for(Model_View_Contact.ENDPOINT_PAGE_CONTACT_SUCCESS))
except Exception as e:
return API.get_standard_response(
success = False,
status_code = 500,
message = f"Error: {e}",
data = None,
errors = [str(e)],
meta = None
)
return API.get_standard_response(
success = False,
status_code = 500,
message = f"Error: {form.errors}",
data = None,
errors = [str(form.errors)],
meta = None
)
# html_body = render_template('pages/core/_contact.html', model = model)
except Exception as e:
return API.get_standard_response(
success = False,
status_code = 500,
message = f"Error: {e}",
data = None,
errors = [str(e)],
meta = None
)
@routes_core_contact.route(Model_View_Contact.HASH_PAGE_CONTACT_SUCCESS, methods=['GET'])
def contact_success():
try:
model = Model_View_Contact_Success()
html_body = render_template('pages/core/_contact_success.html', model = model)
return html_body
except Exception as e:
return API.get_standard_response(
success = False,
status_code = 500,
message = f"Error: {e}",
data = None,
errors = [str(e)],
meta = None
)

View File

@@ -11,8 +11,8 @@ Home Page Controller.
"""
# internal
from business_objects.api import API
from models.model_view_home import Model_View_Home
from dog_training.business_objects.api import API
from dog_training.models.model_view_home import Model_View_Home
# external
from flask import render_template, jsonify, Blueprint

48
controllers/dog/dog.py Normal file
View File

@@ -0,0 +1,48 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Core - Contact Routes
Description:
Contact Page Controller.
"""
# IMPORTS
# internal
from dog_training.business_objects.api import API
from dog_training.business_objects.dog.command import Command
from dog_training.business_objects.dog.dog_command_link import Dog_Command_Link
from dog_training.datastores.datastore_dog import DataStore_Dog
from dog_training.forms.dog.dog_command_link import Filters_Dog_Command_Link
from dog_training.helpers.helper_app import Helper_App
from dog_training.models.model_view_dog_base import Model_View_Dog_Base
from dog_training.models.model_view_home import Model_View_Home
import dog_training.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, flash, Response
from flask_mail import Mail, Message
from dog_training.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
import json
import base64
import hmac
import hashlib
import datetime
from altcha import ChallengeOptions, create_challenge, verify_solution
routes_dog = Blueprint('routes_dog', __name__)
@routes_dog.route(Model_View_Dog_Base.HASH_DOG_SCRIPTS_SHARED, methods=['GET'])
def scripts_section_dog():
hash_page_current = request.args.get('hash_page_current', default = Model_View_Dog_Base.HASH_SCRIPTS_SECTION_STORE, type = str)
model = Model_View_Dog_Base(hash_page_current=hash_page_current)
template = render_template('js/sections/dog.js', model = model)
return Response(template, mimetype='application/javascript')

View File

@@ -0,0 +1,99 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Core - Contact Routes
Description:
Contact Page Controller.
"""
# IMPORTS
# internal
from dog_training.business_objects.api import API
from dog_training.business_objects.dog.command import Command
from dog_training.business_objects.dog.dog_command_link import Dog_Command_Link
from dog_training.datastores.datastore_dog import DataStore_Dog
from dog_training.forms.dog.dog_command_link import Filters_Dog_Command_Link
from dog_training.helpers.helper_app import Helper_App
from dog_training.models.model_view_dog_dog_command_link import Model_View_Dog_Dog_Command_Link
from dog_training.models.model_view_home import Model_View_Home
import dog_training.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, flash
from flask_mail import Mail, Message
from dog_training.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
import json
import base64
import hmac
import hashlib
import datetime
from altcha import ChallengeOptions, create_challenge, verify_solution
routes_dog_dog_command_link = Blueprint('routes_dog_dog_command_link', __name__)
@routes_dog_dog_command_link.route(Model_View_Dog_Dog_Command_Link.HASH_PAGE_DOG_DOG_COMMAND_LINKS, methods=['GET'])
def dog_command_links():
Helper_App.console_log('dog_command_links')
Helper_App.console_log(f'request_args: {request.args}')
try:
form_filters = Filters_Dog_Command_Link.from_json(request.args)
except Exception as e:
Helper_App.console_log(f'Error: {e}')
form_filters = Filters_Dog_Command_Link()
Helper_App.console_log(f'form_filters={form_filters}')
model = Model_View_Dog_Dog_Command_Link(form_filters_old = form_filters)
if not model.is_user_logged_in:
return redirect(url_for('routes_core_home.home'))
return render_template('pages/dog/_dog_command_links.html', model = model)
"""
@routes_dog_dog_command_link.route(Model_View_Dog_Dog_Command_Link.HASH_SAVE_DOG_DOG_COMMAND_LINK, methods=['POST'])
def save_category():
data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Dog_Command_Link.from_json(data[Model_View_Dog_Dog_Command_Link.FLAG_FORM_FILTERS])
if not form_filters.validate_on_submit():
return jsonify({
Model_View_Dog_Dog_Command_Link.FLAG_STATUS: Model_View_Dog_Dog_Command_Link.FLAG_FAILURE,
Model_View_Dog_Dog_Command_Link.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'
})
dog_command_links = data[Model_View_Dog_Dog_Command_Link.FLAG_PRODUCT_CATEGORY]
if len(dog_command_links) == 0:
return jsonify({
Model_View_Dog_Dog_Command_Link.FLAG_STATUS: Model_View_Dog_Dog_Command_Link.FLAG_FAILURE,
Model_View_Dog_Dog_Command_Link.FLAG_MESSAGE: f'No dog command links.'
})
objs_dog_command_link = []
for dog_command_link in dog_command_links:
objs_dog_command_link.append(Dog_Command_Link.from_json(dog_command_link))
Helper_App.console_log(f'objs_dog_command_link={objs_dog_command_link}')
errors = Model_View_Dog_Dog_Command_Link.save_dog_command_links(data.get('comment', 'No comment'), objs_dog_command_link)
model_return = Model_View_Dog_Dog_Command_Link(form_filters_old=form_filters)
if not model_return.is_user_logged_in:
raise Exception('User not logged in')
if (len(errors) > 0):
return jsonify({
Model_View_Dog_Dog_Command_Link.FLAG_STATUS: Model_View_Dog_Dog_Command_Link.FLAG_FAILURE,
Model_View_Dog_Dog_Command_Link.FLAG_MESSAGE: f'Error saving dog command links.\n{model_return.convert_list_objects_to_json(errors)}'
})
return jsonify({
Model_View_Dog_Dog_Command_Link.FLAG_STATUS: Model_View_Dog_Dog_Command_Link.FLAG_SUCCESS,
Model_View_Dog_Dog_Command_Link.FLAG_DATA: model_return.category_list.to_json()
})
except Exception as e:
return jsonify({
Model_View_Dog_Dog_Command_Link.FLAG_STATUS: Model_View_Dog_Dog_Command_Link.FLAG_FAILURE,
Model_View_Dog_Dog_Command_Link.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'
})
"""

View File

@@ -12,13 +12,13 @@ Legal Section Controller.
# 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
# from dog_training.models.model_view_home import Model_View_Home
from dog_training.models.model_view_license import Model_View_License
from dog_training.models.model_view_privacy_policy import Model_View_Privacy_Policy
from dog_training.models.model_view_accessibility_report import Model_View_Accessibility_Report
from dog_training.models.model_view_accessibility_statement import Model_View_Accessibility_Statement
from dog_training.models.model_view_retention_schedule import Model_View_Retention_Schedule
import dog_training.lib.argument_validation as av
# external
from flask import render_template, Blueprint

211
controllers/user/user.py Normal file
View File

@@ -0,0 +1,211 @@
"""
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.dog.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
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import exc
from flask_wtf.csrf import generate_csrf
from werkzeug.exceptions import BadRequest
from extensions import oauth # db,
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
from functools import wraps
db = SQLAlchemy()
routes_user = Blueprint('routes_user', __name__)
def handle_db_disconnect(f):
@wraps(f)
def decorated_function(*args, **kwargs):
try:
return f(*args, **kwargs)
except exc.OperationalError as e:
if "MySQL server has gone away" in str(e):
# Close the session and create a new connection
db.session.remove()
db.session.rollback()
# Retry the operation
return f(*args, **kwargs)
raise
return decorated_function
# User authentication
@routes_user.route("/login", methods=['POST', 'OPTIONS']) # required endpoint for Auth0
def login():
oauth = current_app.extensions['authlib.integrations.flask_client']
try:
Helper_App.console_log('login')
Helper_App.console_log(f'method={request.method}')
try:
data = request.json
try:
data = request.get_json()
except:
data = {}
except:
data = {}
Helper_App.console_log(f'data={data}')
hash_callback = data.get(Model_View_Base.FLAG_CALLBACK, Model_View_Base.HASH_PAGE_HOME)
Helper_App.console_log(f'hash_callback: {hash_callback}')
"""
# Verify CSRF token manually
Helper_App.console_log(f'request headers={request.headers}')
token = request.headers.get(Model_View_Base.FLAG_CSRF_TOKEN)
Helper_App.console_log(f'token={token}')
Helper_App.console_log(f'session={session}')
Helper_App.console_log(f'session token={session.get('csrf_token')}')
if not token or token != session.get('csrf_token'):
token = data.get(Model_View_Base.FLAG_CSRF_TOKEN, None)
Helper_App.console_log(f'token={token}')
if not token or token != session.get('csrf_token'):
raise BadRequest('Invalid or missing CSRF token')
"""
# OAuth login
# callback_login = F'{Model_View_Base.HASH_CALLBACK_LOGIN}{data.get(Model_View_Base.FLAG_CALLBACK, Model_View_Base.HASH_PAGE_HOME)}'
# encoded_path = quote(data.get(Model_View_Base.FLAG_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.FLAG_CALLBACK, Model_View_Base.HASH_PAGE_HOME)}'
Helper_App.console_log(f'redirect uri: {uri_redirect}')
Helper_App.console_log(f'Before red')
Helper_App.console_log(f"Registered clients: {list(oauth._clients.keys())}")
try:
with current_app.app_context():
red = oauth.auth0.authorize_redirect(
redirect_uri = uri_redirect
, state = quote(hash_callback)
)
except Exception as e:
Helper_App.console_log(f"Error: {str(e)}")
Helper_App.console_log(f'redirect: {red}')
headers = red.headers['Location']
Helper_App.console_log(f'headers: {headers}')
parsed_url = urlparse(headers)
query_params = parse_qs(parsed_url.query)
Helper_App.console_log(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.FLAG_CALLBACK}': headers})
return jsonify({'status': 'success', 'redirect': callback})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 400
@routes_user.route("/login_callback")
@handle_db_disconnect
def login_callback():
oauth = current_app.extensions['authlib.integrations.flask_client']
Helper_App.console_log('login_callback')
try:
Helper_App.console_log(f'Redceived state: {request.args.get("state")}')
error_state = request.args.get(Model_View_User.FLAG_ERROR_OAUTH)
has_error = error_state is not None
if has_error:
error_description = request.args.get(Model_View_User.FLAG_ERROR_DESCRIPTION_OAUTH)
error_text = f'Error: {error_state}: {error_description}'
Helper_App.console_log(error_text)
return login()
token = None
try:
token = oauth.auth0.authorize_access_token()
except Exception as e:
Helper_App.console_log(f"Error: {str(e)}")
session[current_app.config['ID_TOKEN_USER']] = token
user = User.from_json_auth0(token)
Helper_App.console_log(f'user: {user}')
filters = Parameters_User.from_user(user)
datastore_user = DataStore_User()
users, errors = datastore_user.get_many_user(filters, user)
try:
user = users[0]
Helper_App.console_log('User logged in')
Helper_App.console_log(f'user ({str(type(user))}): {user}')
Helper_App.console_log(f'user key: {Model_View_Base.FLAG_USER}')
user_json = user.to_json()
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: {Parameters_User}\nDatabase query error: {errors}')
try:
hash_callback = token.get('hash_callback')
if hash_callback is None:
Helper_App.console_log('hash is none')
state = request.args.get('state')
Helper_App.console_log(f'state: {state}')
hash_callback = state
Helper_App.console_log(f'hash_callback: {hash_callback}')
except:
Helper_App.console_log("get hash callback failed")
Helper_App.console_log(f'user session: {session[Model_View_Base.FLAG_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.FLAG_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'],
}
)
Helper_App.console_log(f"Redirecting to {url_logout}")
return redirect(url_logout)
@routes_user.route("/logout_callback")
@handle_db_disconnect
def logout_callback():
return redirect(url_for('routes_core_home.home'))
@routes_user.route("/account")
def user():
try:
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_core_home.home'))
html_body = render_template('pages/user/_user.html', model = model)
except Exception as e:
return str(e)
return html_body

View File

@@ -12,15 +12,13 @@ Datastore for Store
# internal
# from routes import bp_home
import lib.argument_validation as av
from business_objects.sql_error import SQL_Error
from business_objects.project_hub.user import User
# 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
from forms.access_level import Filters_Access_Level
from forms.unit_measurement import Filters_Unit_Measurement
from helpers.helper_app import Helper_App
import dog_training.lib.argument_validation as av
from dog_training.business_objects.sql_error import SQL_Error
from dog_training.business_objects.dog.user import User
# from dog_training.helpers.helper_db_mysql import Helper_DB_MySQL
# from dog_training.models.model_view_store_checkout import Model_View_Store_Checkout # circular!
from dog_training.extensions import db
from dog_training.helpers.helper_app import Helper_App
# external
from sqlalchemy import text
from flask import Flask, session, current_app

201
datastores/datastore_dog.py Normal file
View File

@@ -0,0 +1,201 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: DataStores
Feature: User DataStore
Description:
Datastore for Users
"""
# internal
# from routes import bp_home
import dog_training.lib.argument_validation as av
from dog_training.business_objects.dog.command import Command, Command_Temp
from dog_training.business_objects.dog.dog import Dog
from dog_training.business_objects.dog.dog_command_link import Dog_Command_Link
from dog_training.business_objects.sql_error import SQL_Error
from dog_training.datastores.datastore_base import DataStore_Base
from dog_training.helpers.helper_app import Helper_App
from dog_training.helpers.helper_db_mysql import Helper_DB_MySQL
# from dog_training.models.model_view_store_checkout import Model_View_Store_Checkout # circular!
from dog_training.extensions import db
# external
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class DataStore_Dog(DataStore_Base):
def __init__(self):
super().__init__()
@classmethod
def get_many_dog(cls, filters_dog):
_m = f'{cls.__qualname__}.get_many_dog'
user = cls.get_user_session()
argument_dict = {
'a_id_user': user.id_user
, 'a_get_all_dog': filters_dog.get_all_dog
, 'a_get_inactive_dog': filters_dog.get_inactive_dog
, 'a_ids_dog': filters_dog.ids_dog
, 'a_names_dog': filters_dog.names_dog
, 'a_debug': 0
}
Helper_App.console_log(f'argument_dict: {argument_dict}')
result = cls.db_procedure_execute('p_dog_get_many_dog', argument_dict)
cursor = result.cursor
# Dogs
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw dogs: {result_set_1}')
dogs = []
dog_indexes = {}
for row in result_set_1:
new_dog = Dog.from_db_dog(row)
dog_indexes[new_dog.id_dog] = len(dogs)
dogs.append(new_dog)
# Errors
cursor.nextset()
result_set_e = cursor.fetchall()
Helper_App.console_log(f'raw errors: {result_set_e}')
errors = []
if len(result_set_e) > 0:
errors = [SQL_Error.from_db_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
cls.db_cursor_clear(cursor)
return dogs, errors
@classmethod
def get_many_command(cls, filters_command):
_m = f'{cls.__qualname__}.get_many_command'
user = cls.get_user_session()
argument_dict = {
'a_id_user': user.id_user
, 'a_get_all_command': filters_command.get_all_command
, 'a_get_inactive_command': filters_command.get_inactive_command
, 'a_ids_command': filters_command.ids_command
, 'a_names_command': filters_command.names_command
, 'a_debug': 0
}
Helper_App.console_log(f'argument_dict: {argument_dict}')
result = cls.db_procedure_execute('p_dog_get_many_command', argument_dict)
cursor = result.cursor
# Commands
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw commands: {result_set_1}')
commands = []
command_indexes = {}
for row in result_set_1:
new_command = Command.from_db_command(row)
command_indexes[new_command.id_command] = len(commands)
commands.append(new_command)
# Errors
cursor.nextset()
result_set_e = cursor.fetchall()
Helper_App.console_log(f'raw errors: {result_set_e}')
errors = []
if len(result_set_e) > 0:
errors = [SQL_Error.from_db_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
cls.db_cursor_clear(cursor)
return commands, errors
@classmethod
def get_many_dog_command_link(cls, filters_dog_command_link):
_m = f'{cls.__qualname__}.get_many_dog_command_link'
user = cls.get_user_session()
argument_dict = {
'a_id_user': user.id_user
, 'a_get_all_dog': filters_dog_command_link.get_all_dog
, 'a_get_inactive_dog': filters_dog_command_link.get_inactive_dog
, 'a_ids_dog': filters_dog_command_link.ids_dog
, 'a_get_all_command': filters_dog_command_link.get_all_command
, 'a_get_inactive_command': filters_dog_command_link.get_inactive_command
, 'a_ids_command': filters_dog_command_link.ids_command
, 'a_debug': 0
}
Helper_App.console_log(f'argument_dict: {argument_dict}')
result = cls.db_procedure_execute('p_dog_get_many_dog_command_link', argument_dict)
cursor = result.cursor
# Dog Command Links
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw dog command links: {result_set_1}')
dog_command_links = []
dog_command_link_indexes = {}
for row in result_set_1:
new_dog_command_link = Dog_Command_Link.from_db_dog_command_link(row)
dog_command_link_indexes[new_dog_command_link.id_link] = len(dog_command_links)
dog_command_links.append(new_dog_command_link)
# Errors
cursor.nextset()
result_set_e = cursor.fetchall()
Helper_App.console_log(f'raw errors: {result_set_e}')
errors = []
if len(result_set_e) > 0:
errors = [SQL_Error.from_db_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
cls.db_cursor_clear(cursor)
return dog_command_links, errors
@classmethod
def save_commands(cls, comment, commands):
_m = f'{cls}.save_commands'
av.val_str(comment, 'comment', _m)
guid = Helper_DB_MySQL.create_guid_str()
now = datetime.now()
user = cls.get_user_session()
Helper_App.console_log(f'saving commands: {commands}')
rows = []
for command in commands:
row = Command_Temp.from_command(command)
row.guid = guid
rows.append(row)
cls.upload_bulk(Command_Temp.__tablename__, rows, 1000)
Helper_App.console_log('Commands uploaded')
argument_dict_list = {
'a_comment': comment,
'a_guid': guid,
'a_id_user': user.id_user,
'a_debug': 0
}
result = cls.db_procedure_execute('p_dog_save_command', argument_dict_list)
Helper_App.console_log('Commands saved')
# Errors
cursor = result.cursor
cursor.nextset()
result_set_e = cursor.fetchall()
errors = []
if len(result_set_e) > 0:
errors = [SQL_Error.from_db_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
cls.db_cursor_clear(cursor)
return errors

View File

@@ -0,0 +1,119 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: DataStores
Feature: User DataStore
Description:
Datastore for Users
"""
# internal
# from routes import bp_home
import lib.argument_validation as av
from business_objects.sql_error import SQL_Error
from business_objects.dog.user import User, Parameters_User, User_Permission_Evaluation
from datastores.datastore_base import DataStore_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!
from extensions import db
# external
# from abc import ABC, abstractmethod, abstractproperty
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
import stripe
import os
from flask import Flask, session, current_app
from pydantic import BaseModel, ConfigDict
from typing import ClassVar
from datetime import datetime
db = SQLAlchemy()
class DataStore_User(DataStore_Base):
def __init__(self):
super().__init__()
def edit_user(self):
_m = 'DataStore_User.edit_user'
# guid = Helper_DB_MySQL.create_guid()
argument_dict_list = {
'a_id_user': self.info_user.get('sub'),
'a_name': self.info_user.get('name'),
'a_email': self.info_user.get('email'),
'a_email_verified': 1 if self.info_user.get('email_verified') == 'True' else 0
}
result = self.db_procedure_execute('p_dog_save_user', argument_dict_list)
cursor = result.cursor
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw user data: {result_set_1}')
# Errors
cursor.nextset()
result_set_e = cursor.fetchall()
Helper_App.console_log(f'raw errors: {result_set_e}')
if len(result_set_e) > 0:
errors = [SQL_Error.from_DB_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
DataStore_User.db_cursor_clear(cursor)
return (result_set_1[0][1] == b'\x01')
def get_many_user(self, user_filters, user=None):
_m = 'DataStore_User.get_many_user'
Helper_App.console_log(_m)
Helper_App.console_log(f'user_filters: {user_filters}')
Helper_App.console_log(f"valid user_filters: {av.val_instance(user_filters, 'user_filters', _m, Parameters_User)}")
# guid = Helper_DB_MySQL.create_guid()
Helper_App.console_log(f'user: {user}')
if user is None:
user = self.get_user_session()
Helper_App.console_log(f'user: {user}')
argument_dict_list = {
'a_id_user': user.id_user
, 'a_id_user_auth0': user.id_user_auth0
, **user_filters.to_json()
, 'a_debug': 0
}
Helper_App.console_log(f'argument_dict_list: {argument_dict_list}')
result = self.db_procedure_execute('p_dog_get_many_user', argument_dict_list)
cursor = result.cursor
result_set = cursor.fetchall()
Helper_App.console_log(f'raw users: {result_set}')
Helper_App.console_log(f'type result set: {str(type(result_set))}')
Helper_App.console_log(f'len result set: {len(result_set)}')
users = []
if len(result_set) > 0:
for row in result_set:
Helper_App.console_log(f'row: {row}')
user = User.from_DB_user(row)
users.append(user)
Helper_App.console_log(f'user {str(type(user))}: {user}')
Helper_App.console_log(f'type users: {str(type(users))}\n type user 0: {str(type(None if len(users) == 0 else users[0]))}')
"""
errors = []
cursor.nextset()
result_set_e = cursor.fetchall()
Helper_App.console_log(f'raw errors: {result_set_e}')
if len(result_set_e) > 0:
errors = [SQL_Error.from_DB_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
"""
errors = None
DataStore_User.db_cursor_clear(cursor)
return users, errors

View File

@@ -1,113 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: DataStores
Feature: User DataStore
Description:
Datastore for Users
"""
# internal
# from routes import bp_home
import lib.argument_validation as av
from business_objects.sql_error import SQL_Error
from business_objects.project_hub.command import Command, Command_Temp
from datastores.datastore_base import DataStore_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!
from extensions import db
# external
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class DataStore_Command(DataStore_Base):
def __init__(self):
super().__init__()
@classmethod
def get_many_command(cls):
_m = f'{cls.__qualname__}.get_many_command'
user = cls.get_user_session()
argument_dict = {
'a_id_user': user.id_user
, 'a_debug': 0
}
Helper_App.console_log(f'argument_dict: {argument_dict}')
result = cls.db_procedure_execute('p_ph_get_many_command', argument_dict)
cursor = result.cursor
# Commands
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw commands: {result_set_1}')
commands = []
command_indexes = {}
for row in result_set_1:
new_command = Command.from_DB_command(row)
command_indexes[new_command.id_command] = len(commands)
commands.append(new_command)
# Errors
cursor.nextset()
result_set_e = cursor.fetchall()
Helper_App.console_log(f'raw errors: {result_set_e}')
errors = []
if len(result_set_e) > 0:
errors = [SQL_Error.from_DB_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
cls.db_cursor_clear(cursor)
return commands, errors
@classmethod
def save_commands(cls, comment, commands):
_m = f'{cls}.save_commands'
av.val_str(comment, 'comment', _m)
guid = Helper_DB_MySQL.create_guid_str()
now = datetime.now()
user = cls.get_user_session()
Helper_App.console_log(f'saving commands: {commands}')
rows = []
for command in commands:
row = Command_Temp.from_command(command)
row.guid = guid
rows.append(row)
cls.upload_bulk(Command_Temp.__tablename__, rows, 1000)
Helper_App.console_log('Commands uploaded')
argument_dict_list = {
'a_comment': comment,
'a_guid': guid,
'a_id_user': user.id_user,
'a_debug': 0
}
result = cls.db_procedure_execute('p_ph_save_command', argument_dict_list)
Helper_App.console_log('Commands saved')
# Errors
cursor = result.cursor
cursor.nextset()
result_set_e = cursor.fetchall()
errors = []
if len(result_set_e) > 0:
errors = [SQL_Error.from_DB_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
cls.db_cursor_clear(cursor)
return errors

View File

@@ -1,37 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Backend
Feature: Forms - Access Level Filters data input
Description:
Defines Flask-WTF forms for handling access level filter input.
"""
# internal
from business_objects.base import Base
from forms.base import Form_Base
import lib.argument_validation as av
# external
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField
from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional
from flask_wtf.recaptcha import RecaptchaField
from abc import ABCMeta, abstractmethod
class Filters_Access_Level(Form_Base):
active = BooleanField("Active only?", default = True)
def __repr__(self):
return f'{self.__class__.__name__}(active={self.active.data})'
@classmethod
def from_json(cls, json):
form = Filters_Access_Level()
form.active.data = av.input_bool(json[Base.FLAG_ACTIVE], Base.FLAG_ACTIVE, f'{cls.__name__}.from_json')
return form
def to_json(self):
return {
Base.FLAG_ACTIVE: 1 if av.input_bool(self.active.data, Base.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0,
}

View File

@@ -11,9 +11,12 @@ Defines Flask-WTF base forms for handling user input.
"""
# internal
from dog_training.helpers.helper_app import Helper_App
# external
from flask_wtf import FlaskForm
from abc import ABCMeta, abstractmethod
from wtforms import SelectField, BooleanField, SubmitField
from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional
class Form_Base_Meta(type(FlaskForm), ABCMeta):
@@ -21,45 +24,30 @@ class Form_Base_Meta(type(FlaskForm), ABCMeta):
class Form_Base(FlaskForm, metaclass=Form_Base_Meta):
"""
@classmethod
@abstractmethod
def from_filters(cls, filters):
pass
@abstractmethod
def __repr__(self):
pass
"""
def from_json(cls, json):
Helper_App.console_log(f'Error: Parent classes of {cls.__qualname__} must define cls.from_json')
@classmethod
def get_default(cls):
return cls()
@classmethod
def get_select_option_blank(cls):
return (cls.get_select_option_default_value(), 'Select')
@classmethod
def get_select_option_all(cls):
return (cls.get_select_option_default_value(), 'All')
@staticmethod
def get_select_option_default_value():
return ''
def __repr__(self):
fields = ', '.join(
f"{name}={field.data}" for name, field in self._fields.items()
)
return f"{self.__class__.__name__}({fields})"
@classmethod
@abstractmethod
def from_json(cls, json):
pass
@classmethod
def get_default(cls):
return cls()
"""
@abstractmethod
def test_69(self):
pass
def get_Filters_Product_Category(data_request):
data_form = data_request[Model_View_Store_Product_Category.FLAG_FORM]
form_filters = Filters_Product_Category(**data_form)
form_filters.is_not_empty.data = av.input_bool(data_form['is_not_empty'], 'is_not_empty', 'filter_category')
form_filters.active.data = av.input_bool(data_form['active'], 'active', 'filter_category')
return form_filters
"""
@classmethod
def get_choices_blank(cls):
return [('', 'Select')]
@classmethod
def get_choice_all(cls):
return ('', 'All')
'''
class Filters_Stored_Procedure_Base(Form_Base):
@@ -75,4 +63,10 @@ class Filters_Stored_Procedure_Base(Form_Base):
@abstractmethod
def to_json(self):
pass
'''
'''
class Form_Filters_User(FlaskForm):
active = BooleanField('Active only?', default = True)
id_user = SelectField('User ID', validators=[Optional()], choices=[])

View File

@@ -1,100 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Backend
Feature: Contact Us Form
Description:
Defines Flask-WTF form for handling user input on Contact Us page.
"""
# IMPORTS
# internal
from business_objects.base import Base
from business_objects.project_hub.command import Command
# from models.model_view_store import Model_View_Store # circular
from models.model_view_base import Model_View_Base
from forms.base import Form_Base
# external
from flask import Flask, render_template, request, flash, redirect, url_for, current_app
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField, HiddenField, BooleanField, Field, EmailField
from wtforms.validators import DataRequired, Email, ValidationError
import markupsafe
from flask_wtf.recaptcha import RecaptchaField
from abc import ABCMeta, abstractmethod
import json
from altcha import verify_solution
import base64
class ALTCHAValidator:
def __init__(self, message=None):
self.message = message or 'ALTCHA verification failed'
def __call__(self, form, field):
altcha_data = field.data
if not altcha_data:
raise ValidationError(self.message)
try:
# The data is base64 encoded JSON
try:
# First try to decode it as JSON directly (if it's not base64 encoded)
altcha_payload = json.loads(altcha_data)
except json.JSONDecodeError:
# If direct JSON decoding fails, try base64 decoding first
decoded_data = base64.b64decode(altcha_data).decode('utf-8')
altcha_payload = json.loads(decoded_data)
ok, err = verify_solution(altcha_payload, current_app.app_config.ALTCHA_SECRET_KEY, check_expires=True)
if err or not ok:
raise ValidationError(self.message + ': ' + (err or 'Invalid solution'))
except Exception as e:
raise ValidationError(f'Invalid ALTCHA data: {str(e)}')
class ALTCHAField(Field):
def __init__(self, label='', validators=None, **kwargs):
validators = validators or []
validators.append(ALTCHAValidator())
super(ALTCHAField, self).__init__(label, validators, **kwargs)
def __call__(self, **kwargs):
html = f"""
<altcha-widget
challengeurl="/get-challenge"
auto="onload"
id="{self.id}"
name="{self.name}">
</altcha-widget>
"""
return markupsafe.Markup(html)
class Form_Contact(FlaskForm):
email = EmailField('Email')
contact_name = StringField('Name')
company_name = StringField('Company')
message = TextAreaField('Message')
receive_marketing = BooleanField('I would like to receive marketing emails.')
# recaptcha = RecaptchaField()
# altcha = HiddenField('ALTCHA') # , validators=[validate_altcha]
altcha = ALTCHAField('Verify you are human')
submit = SubmitField('Send Message')
def to_json(self):
return {
Base.FLAG_EMAIL: self.email.data
, Command.FLAG_NAME_CONTACT: self.contact_name.data
, Command.FLAG_NAME_COMPANY: self.company_name.data
, Command.FLAG_MESSAGE: self.message.data
, Command.FLAG_RECEIVE_MARKETING_COMMUNICATIONS: self.receive_marketing.data
, Command.FLAG_ALTCHA: self.altcha.data
, Base.FLAG_ACTIVE: True
, Base.FLAG_CREATED_ON: None
}

View File

@@ -0,0 +1,64 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Backend
Feature: Contact Us Form
Description:
Defines Flask-WTF form for handling user input on Contact Us page.
"""
# IMPORTS
# internal
from dog_training.business_objects.base import Base
from dog_training.business_objects.dog.command import Command
from dog_training.business_objects.dog.dog import Dog
from dog_training.business_objects.dog.obedience_level import Obedience_Level
# from dog_training.models.model_view_store import Model_View_Store # circular
# from dog_training.models.model_view_base import Model_View_Base
from dog_training.forms.base import Form_Base
import dog_training.lib.argument_validation as av
# external
from flask import Flask, render_template, request, flash, redirect, url_for, current_app
from flask_wtf import FlaskForm
from wtforms import SelectField, BooleanField, SubmitField
from wtforms.validators import DataRequired, Email, ValidationError
import markupsafe
from flask_wtf.recaptcha import RecaptchaField
from abc import ABCMeta, abstractmethod
import json
class Filters_Dog_Command_Link(Form_Base):
id_dog = SelectField(
'Dog'
, choices = [Form_Base.get_select_option_all()]
, default = Form_Base.get_select_option_default_value()
)
id_command = SelectField(
'Command'
, choices = [Form_Base.get_select_option_all()]
, default = Form_Base.get_select_option_default_value()
)
active_only = BooleanField(
'Active'
, default = True
)
@classmethod
def from_json(cls, json):
filters = cls()
filters.id_dog.choices = [(json[Dog.ATTR_ID_DOG], json[Dog.ATTR_ID_DOG])]
filters.id_dog.data = json[Dog.ATTR_ID_DOG]
filters.id_command.choices = [(json[Command.ATTR_ID_COMMAND], json[Command.ATTR_ID_COMMAND])]
filters.id_command.data = json[Command.ATTR_ID_COMMAND]
filters.active_only.data = av.input_bool(json[Base.FLAG_ACTIVE], Base.FLAG_ACTIVE, f'{cls.__name__}.from_json')
return filters
def to_json(self):
return {
Dog.FLAG_DOG: self.id_dog.data
, Command.FLAG_COMMAND: self.id_command.data
, Base.FLAG_ACTIVE: self.active_only.data
}

View File

@@ -1,134 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Backend
Feature: Forms - User data input
Description:
Defines Flask-WTF forms for handling user input.
"""
# IMPORTS
# internal
# from business_objects.store.product_category import Filters_Product_Category # circular
# from models.model_view_store import Model_View_Store # circular
from forms.base import Form_Base
# external
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField
from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional
from flask_wtf.recaptcha import RecaptchaField
from abc import ABCMeta, abstractmethod
class Form_Contact(FlaskForm):
email = StringField('Email address')
CC = BooleanField('Would you like to receive a copy of this email request?') # not in use
name = StringField('Name')
message = TextAreaField('Message')
recaptcha = RecaptchaField()
submit = SubmitField('Submit')
class Form_Register(FlaskForm):
email = StringField('Email address')
CC = BooleanField('Would you like to receive a copy of this email request?') # not in use
name = StringField('Name')
message = TextAreaField('Message')
submit = SubmitField('Submit')
"""
class Form_Product(FlaskForm): # for basket, product tiles, product add
# PositiveIntegerField with validation constraints
quantity = IntegerField(
'Quantity',
validators=[
# InputRequired(message='Quantity'),
NumberRange(min=1, message='Please enter a positive integer')
],
default=1
)
"""
class Form_Basket_Add(FlaskForm): # for basket, product tiles, product add
# PositiveIntegerField with validation constraints
quantity = IntegerField(
'Quantity',
validators=[
# InputRequired(message='Quantity'),
NumberRange(min=1, message='Please enter a positive integer')
],
default=1
# render_kw={'id-product': ''} # {Model_View_Store.attr_id_product: ''}
)
submit = SubmitField('Add')
form_type = 'Form_Basket_Add'
class Form_Basket_Edit(FlaskForm): # for basket, product tiles, product add
# PositiveIntegerField with validation constraints
quantity = IntegerField(
'Quantity',
validators=[
# InputRequired(message='Quantity'),
NumberRange(min=1, message='Please enter a positive integer')
],
default=1
# render_kw={'id-product': ''} # {Model_View_Store.attr_id_product: ''}
)
submit = SubmitField('Update')
form_type = 'Form_Basket_Edit'
class Form_Billing(FlaskForm):
identical = BooleanField('Use delivery address')
region = SelectField('Country / region', choices=[('uk', 'UK'), ('international', 'International')], validators=[DataRequired()])
name_full = StringField('Full name')
phone_number = StringField('Phone number', validators=[Regexp(r'^\+?[0-9\s]{5,20}$', message='Only numbers, plus symbol, and space are allowed.'), DataRequired()])
postcode = StringField('Post code', validators=[DataRequired()])
address_1 = StringField('Address line 1', validators=[DataRequired()])
address_2 = StringField('Address line 2 (optional)')
city = StringField('City', validators=[DataRequired()])
county = StringField('County', validators=[DataRequired()])
submit = SubmitField('Submit')
form_type_billing_not_delivery = False
def output_id(self):
return 'formBilling' if self.form_type_billing_not_delivery else 'formDeliver'
class Form_Is_Included_VAT(FlaskForm):
is_included = BooleanField('Include VAT')
class Form_Delivery_Region(FlaskForm):
id_id_region_delivery = 'id_region_delivery'
id_region_delivery = SelectField('Region', id='id_region_delivery')
class Form_Currency(FlaskForm):
id_id_currency = 'id_currency'
id_currency = SelectField('Currency', id='id_currency')
# Store
class Form_Supplier(FlaskForm):
id_id_supplier = 'id_supplier'
id_supplier = SelectField('Supplier', id='id_supplier')
name_company = StringField('Company name')
name_contact = StringField('Contact name')
department_contact = StringField('Contact department')
id_address = SelectField('Address ID')
phone_number = StringField('Phone number')
email = StringField('Email address')
fax = StringField('Fax number')
website = StringField('Website')
id_currency = SelectField('Currency ID')
is_active = BooleanField('Active', default = True)
# class Form_Supplier_Purchase_Order(FlaskForm):
# User
class Form_Filters_User(FlaskForm):
active = BooleanField('Active only?', default = True)
id_user = SelectField('User ID', validators=[Optional()], choices=[])

View File

@@ -1,42 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Backend
Feature: Forms - Unit of Measurement Filters data input
Description:
Defines Flask-WTF forms for handling unit of measurement filter input.
"""
# internal
from business_objects.base import Base
from forms.base import Form_Base
import lib.argument_validation as av
# external
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField
from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional
from flask_wtf.recaptcha import RecaptchaField
from abc import ABCMeta, abstractmethod
class Filters_Unit_Measurement(Form_Base):
active = BooleanField("Active only?", default = True)
@classmethod
def from_filters(cls, filters):
form = Filters_Unit_Measurement()
form.active.data = filters.active
return form
def __repr__(self):
return f'Filters_Unit_Measurement(active={self.active.data})'
@classmethod
def from_json(cls, json):
form = Filters_Unit_Measurement()
form.active.data = av.input_bool(json[Base.FLAG_ACTIVE], 'active', 'Filters_Unit_Measurement')
return form
def to_json(self):
return {
Base.FLAG_ACTIVE: av.input_bool(self.active.data, Base.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'),
}

View File

@@ -7,7 +7,7 @@ Created on Thu Apr 27 12:33:59 2023
Argument Validation
"""
from helpers.helper_app import Helper_App
from dog_training.helpers.helper_app import Helper_App
from typing import Optional
def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):

View File

@@ -11,7 +11,7 @@ Data model for accessibility report view
"""
# internal
from models.model_view_base import Model_View_Base
from dog_training.models.model_view_base import Model_View_Base
# from routes import bp_home
# external

View File

@@ -11,7 +11,7 @@ Data model for accessibility statement view
"""
# internal
from models.model_view_base import Model_View_Base
from dog_training.models.model_view_base import Model_View_Base
# from routes import bp_home
# external

View File

@@ -17,16 +17,13 @@ Base data model for views
# IMPORTS
# internal
# from routes import bp_home
from business_objects.base import Base
from business_objects.project_hub.user import User
from business_objects.project_hub.command import Command
from datastores.datastore_base import DataStore_Base
from datastores.project_hub.datastore_command import DataStore_Command
from forms.access_level import Filters_Access_Level
from forms.forms import Form_Is_Included_VAT, Form_Delivery_Region, Form_Currency
from forms.unit_measurement import Filters_Unit_Measurement
from helpers.helper_app import Helper_App
import lib.argument_validation as av
from dog_training.business_objects.base import Base
from dog_training.business_objects.dog.user import User
from dog_training.business_objects.dog.command import Command
from dog_training.datastores.datastore_base import DataStore_Base
from dog_training.datastores.datastore_dog import DataStore_Dog
from dog_training.helpers.helper_app import Helper_App
import dog_training.lib.argument_validation as av
# external
from abc import ABC, abstractmethod
from flask_sqlalchemy import SQLAlchemy
@@ -105,8 +102,16 @@ class Model_View_Base(BaseModel, ABC):
FLAG_NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.FLAG_NAME_ATTR_OPTION_VALUE
FLAG_NAME_PLURAL: ClassVar[str] = Base.FLAG_NAME_PLURAL
# FLAG_NAME_SINGULAR: ClassVar[str] = Base.FLAG_NAME_SINGULAR
FLAG_NAV_ADMIN_HOME: ClassVar[str] = 'navAdminHome'
FLAG_NAV_CONTACT: ClassVar[str] = 'navContact'
FLAG_NAV_DOG_COMMAND: ClassVar[str] = 'navDogCommand'
FLAG_NAV_DOG_DOG: ClassVar[str] = 'navDogDog'
FLAG_NAV_DOG_DOG_COMMAND_LINK: ClassVar[str] = 'navDogDogCommandLink'
FLAG_NAV_HOME: ClassVar[str] = 'navHome'
FLAG_NAV_USER_ACCOUNT: ClassVar[str] = 'navUserAccount'
FLAG_NAV_USER_ADMIN: ClassVar[str] = 'navUserAdmin'
FLAG_NAV_USER_LOGIN: ClassVar[str] = 'navUserLogin'
FLAG_NAV_USER_LOGOUT: ClassVar[str] = 'navUserLogout'
FLAG_OVERLAY: ClassVar[str] = 'overlay'
FLAG_PAGE_BODY: ClassVar[str] = 'page-body'
FLAG_RIGHT_HAND_SIDE: ClassVar[str] = 'rhs'
@@ -125,6 +130,7 @@ class Model_View_Base(BaseModel, ABC):
HASH_GET_ALTCHA_CHALLENGE: ClassVar[str] = '/altcha/create-challenge'
HASH_PAGE_ACCESSIBILITY_REPORT: ClassVar[str] = '/accessibility-report'
HASH_PAGE_ACCESSIBILITY_STATEMENT: ClassVar[str] = '/accessibility-statement'
HASH_PAGE_ADMIN_HOME: ClassVar[str] = '/admin'
HASH_PAGE_CONTACT: ClassVar[str] = '/contact'
HASH_PAGE_CONTACT_SUCCESS: ClassVar[str] = '/contact-success'
HASH_PAGE_DATA_RETENTION_SCHEDULE: ClassVar[str] = '/retention-schedule'
@@ -132,6 +138,9 @@ class Model_View_Base(BaseModel, ABC):
HASH_PAGE_HOME: ClassVar[str] = '/'
HASH_PAGE_LICENSE: ClassVar[str] = '/license'
HASH_PAGE_PRIVACY_POLICY: ClassVar[str] = '/privacy-policy'
HASH_PAGE_USER_ACCOUNT: ClassVar[str] = '/user'
HASH_PAGE_USER_LOGIN: ClassVar[str] = '/login'
HASH_PAGE_USER_LOGOUT: ClassVar[str] = '/logout'
ID_BUTTON_ADD: ClassVar[str] = 'buttonAdd'
ID_BUTTON_APPLY_FILTERS: ClassVar[str] = 'buttonApplyFilters'
ID_BUTTON_CANCEL: ClassVar[str] = 'buttonCancel'

View File

@@ -1,35 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: View Models
Feature: Contact View Model
Description:
Data model for contact view
"""
# internal
from business_objects.project_hub.command import Command
from models.model_view_base import Model_View_Base
# from routes import bp_home
from lib import argument_validation as av
from forms.contact import Form_Contact
# external
from flask_wtf import FlaskForm
from abc import abstractproperty
from pydantic import BaseModel
from typing import ClassVar
class Model_View_Contact(Model_View_Base):
form_contact: Form_Contact
@property
def title(self):
return 'Contact'
def __init__(self, form_contact, hash_page_current=Model_View_Base.HASH_PAGE_CONTACT, **kwargs):
super().__init__(hash_page_current=hash_page_current, form_contact=form_contact, **kwargs)
# self.form = form

View File

@@ -1,31 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: View Models
Feature: Contact View Model
Description:
Data model for contact view
"""
# internal
from models.model_view_base import Model_View_Base
# from routes import bp_home
from lib import argument_validation as av
# from forms.contact import Form_Contact
# external
from flask_wtf import FlaskForm
from abc import abstractproperty
from pydantic import BaseModel
from typing import ClassVar
class Model_View_Contact_Success(Model_View_Base):
@property
def title(self):
return 'Contact Success'
def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_CONTACT_SUCCESS, **kwargs):
super().__init__(hash_page_current=hash_page_current, **kwargs)

View File

@@ -0,0 +1,59 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: View Models
Feature: Store Parent View Model
Description:
Parent data model for store views
"""
# internal
# from context import models
from dog_training.business_objects.dog.dog import Dog, Parameters_Dog
from dog_training.datastores.datastore_dog import DataStore_Dog
from dog_training.helpers.helper_app import Helper_App
import dog_training.lib.argument_validation as av
from dog_training.models.model_view_base import Model_View_Base
# external
from flask import send_file, jsonify
from flask_sqlalchemy import SQLAlchemy
import locale
from typing import ClassVar
from abc import abstractmethod
class Model_View_Dog_Base(Model_View_Base):
# ATTR_FORM_TYPE: ClassVar[str] = 'form-type'
# ATTR_ID_CUSTOMER: ClassVar[str] = 'id-customer'
# ATTR_ID_CUSTOMER_ADDRESS: ClassVar[str] = Store_Base.ATTR_ID_CUSTOMER_ADDRESS
# FLAG_CURRENCY_COST: ClassVar[str] = Product_Permutation.FLAG_CURRENCY_COST
# FLAG_CUSTOMER: ClassVar[str] = Store_Base.FLAG_CUSTOMER
# FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = Product_Permutation.FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY
# FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: ClassVar[str] = Product_Permutation.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED
# HASH_GET_STORE_CUSTOMER_SALES_ORDER: ClassVar[str] = '/store/customer_sales_order_get'
# HASH_GET_STORE_MANUFACTURING_PURCHASE_ORDER: ClassVar[str] = '/store/manufacturing_purchase_order_get'
HASH_DOG_SCRIPTS_SHARED: ClassVar[str] = '/dog/scripts_shared'
HASH_PAGE_DOG_DOG_COMMAND_LINKS: ClassVar[str] = '/dog/dog_command_links'
@property
def title(self):
raise NotImplementedError('title must be implemented in child class')
def __init__(self, hash_page_current, **kwargs):
_m = 'Model_View_Dog_Base.__init__'
Helper_App.console_log(f'{_m}\nstarting')
super().__init__(hash_page_current=hash_page_current, **kwargs)
self.is_page_store = True
"""
def get_many_dog(self, dog_filters):
_m = 'Model_View_Dog_Base.get_many_dog'
av.val_instance(dog_filters, 'dog_filters', _m, Parameters_Dog)
return DataStore_Dog().get_many_dog(dog_filters)
"""

View File

@@ -0,0 +1,64 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: View Models
Feature: Store Permutations View Model
Description:
Data model for store permutations view
"""
# internal
from dog_training.business_objects.dog.command import Command, Parameters_Command
from dog_training.business_objects.dog.dog import Dog, Parameters_Dog
from dog_training.business_objects.dog.dog_command_link import Dog_Command_Link, Parameters_Dog_Command_Link
from dog_training.business_objects.dog.obedience_level import Obedience_Level
from dog_training.datastores.datastore_dog import DataStore_Dog
from dog_training.models.model_view_dog_base import Model_View_Dog_Base
from dog_training.forms.dog.dog_command_link import Filters_Dog_Command_Link
# from routes import bp_home
from dog_training.helpers.helper_app import Helper_App
import dog_training.lib.argument_validation as av
# external
from pydantic import BaseModel
from typing import ClassVar
class Model_View_Dog_Dog_Command_Link(Model_View_Dog_Base):
filter_dogs: list = None
filter_commands: list = None
dog_command_links: list = None
form_filters: Filters_Dog_Command_Link = None
form_filters_old: Filters_Dog_Command_Link
@property
def title(self):
return 'Dog Command Link'
def __init__(self, form_filters_old, hash_page_current=Model_View_Dog_Base.HASH_PAGE_DOG_DOG_COMMAND_LINKS):
_m = 'Model_View_Dog_Dog_Command_Link.__init__'
Helper_App.console_log(f'{_m}\nstarting...')
super().__init__(hash_page_current=hash_page_current, form_filters_old=form_filters_old)
self.form_filters = form_filters_old
datastore = DataStore_Dog()
parameters_filter_dog = Parameters_Dog.get_default()
self.filter_dogs, errors = datastore.get_many_dog(parameters_filter_dog)
parameters_filter_command = Parameters_Command.get_default()
self.filter_commands, errors = datastore.get_many_command(parameters_filter_command)
parameters_filter_dog_command_link = Parameters_Dog_Command_Link.get_default()
self.dog_command_links, errors = datastore.get_many_dog_command_link(parameters_filter_dog_command_link)
Helper_App.console_log(f'dogs: {self.filter_dogs}')
Helper_App.console_log(f'commands: {self.filter_commands}')
Helper_App.console_log(f'links: {self.dog_command_links}')
"""
@classmethod
def save_categories(cls, comment, list_categories):
_m = f'{cls.__name__}.save_categories'
return DataStore_Store_Product_Category().save_categories(comment, list_categories)
"""

View File

@@ -11,7 +11,7 @@ Data model for home view
"""
# internal
from models.model_view_base import Model_View_Base
from dog_training.models.model_view_base import Model_View_Base
# from routes import bp_home
# external

View File

@@ -11,7 +11,7 @@ Data model for license view
"""
# internal
from models.model_view_base import Model_View_Base
from dog_training.models.model_view_base import Model_View_Base
# from routes import bp_home
# external

View File

@@ -11,7 +11,7 @@ Data model for privacy policy view
"""
# internal
from models.model_view_base import Model_View_Base
from dog_training.models.model_view_base import Model_View_Base
# from routes import bp_home
# external

View File

@@ -11,7 +11,7 @@ Data model for retention schedule view
"""
# internal
from models.model_view_base import Model_View_Base
from dog_training.models.model_view_base import Model_View_Base
# from routes import bp_home
# external

38
models/model_view_user.py Normal file
View File

@@ -0,0 +1,38 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: View Models
Feature: User View Model
Description:
Data model for user view
"""
# internal
from datastores.datastore_user import DataStore_User
from models.model_view_base import Model_View_Base
# from routes import bp_home
# external
from typing import ClassVar
class Model_View_User(Model_View_Base):
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'
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):
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()

View File

@@ -14,7 +14,7 @@ Manages the interaction between the frontend and backend.
from flask import render_template, url_for, Blueprint
from app import app
from app.forms import Form_Contact
# from forms import MyForm
# from dog_training.forms import MyForm
# from app import MyForm
from model_view_contact import Model_View_Contact

View File

@@ -0,0 +1,759 @@
USE demo;
DROP PROCEDURE IF EXISTS demo.p_DOG_get_many_dog;
DELIMITER //
CREATE PROCEDURE demo.p_DOG_get_many_dog (
IN a_id_user INT
, IN a_get_all_dog BIT
, IN a_get_inactive_dog BIT
, IN a_ids_dog TEXT
, IN a_names_dog TEXT
, IN a_debug BIT
)
BEGIN
DECLARE v_code_type_error_bad_data VARCHAR(100);
DECLARE v_code_type_error_no_permission VARCHAR(100);
DECLARE v_id_type_error_bad_data INT;
DECLARE v_id_type_error_no_permission INT;
DECLARE v_has_filter_dog_id BIT;
DECLARE v_has_filter_dog_name BIT;
DECLARE v_guid BINARY(36);
DECLARE v_id_permission_dog_view INT;
DECLARE v_id_minimum INT;
DECLARE v_time_start TIMESTAMP(6);
DECLARE v_can_view BIT;
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 (
id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT
, id_type INT NULL
, code VARCHAR(100) NOT NULL
, msg VARCHAR(4000) NOT NULL
);
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
MET.id_type
, @errno
, @text
FROM demo.CORE_Msg_Error_Type MET
WHERE MET.code = 'MYSQL_ERROR'
;
SELECT
t_ERROR.id_error
, t_ERROR.id_type
, t_ERROR.code
, ERROR_TYPE.name
, ERROR_TYPE.description
, ERROR_TYPE.is_breaking_error
, ERROR_TYPE.background_colour
, ERROR_TYPE.text_colour
, t_ERROR.msg
FROM tmp_Msg_Error t_ERROR
INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type
;
DROP TABLE IF EXISTS tmp_Msg_Error;
END;
SET v_time_start := CURRENT_TIMESTAMP(6);
SET v_guid := UUID();
SET v_code_type_error_bad_data := 'BAD_DATA';
SET v_code_type_error_no_permission := 'NO_PERMISSION';
SET v_id_type_error_bad_data := (SELECT ERROR_TYPE.id_type FROM demo.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_bad_data LIMIT 1);
SET v_id_type_error_no_permission := (SELECT ERROR_TYPE.id_type FROM demo.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_no_permission LIMIT 1);
SET v_id_permission_dog_view := (SELECT PERMISSION.id_permission FROM demo.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_VIEW' LIMIT 1);
SET a_id_user := IFNULL(a_id_user, 0);
SET a_get_all_dog := IFNULL(a_get_all_dog, 0);
SET a_get_inactive_dog := IFNULL(a_get_inactive_dog, 0);
SET a_ids_dog := TRIM(IFNULL(a_ids_dog, ''));
SET a_names_dog := TRIM(IFNULL(a_names_dog, ''));
SET a_debug := IFNULL(a_debug, 0);
IF a_debug = 1 THEN
SELECT
a_id_user
, a_get_all_dog
, a_get_inactive_dog
, a_ids_dog
, a_names_dog
, a_debug
;
SELECT
v_id_type_error_bad_data
, v_id_type_error_no_permission
, v_guid
, v_id_permission_dog_view
, v_time_start
;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp_Split_Name;
DROP TEMPORARY TABLE IF EXISTS tmp_Split_Id;
DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error;
DROP TEMPORARY TABLE IF EXISTS tmp_Dog;
CREATE TEMPORARY TABLE tmp_Dog (
id_dog INT NOT NULL
, name VARCHAR(250)
);
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error (
id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT
, id_type INT NULL
, code VARCHAR(100) NOT NULL
, msg VARCHAR(4000) NOT NULL
);
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split_Id (
substring VARCHAR(4000) NOT NULL
, as_int INT NULL
);
DELETE FROM tmp_Split_Id;
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split_Name (
substring VARCHAR(4000) NOT NULL
, as_int INT NULL
);
DELETE FROM tmp_Split_Name;
CALL demo.p_core_validate_guid ( v_guid );
SET v_has_filter_dog_id = CASE WHEN a_ids_dog = '' THEN 0 ELSE 1 END;
SET v_has_filter_dog_name = CASE WHEN a_names_dog = '' THEN 0 ELSE 1 END;
-- Dogs
IF v_has_filter_dog_id = 1 THEN
CALL demo.p_split(v_guid, a_ids_dog, ',', a_debug);
INSERT INTO tmp_Split_Id (
substring
, as_int
)
SELECT
SPLIT_T.substring
, CONVERT(SPLIT_T.substring, DECIMAL(10,0)) AS as_int
FROM demo.CORE_Split_Temp SPLIT_T
WHERE
SPLIT_T.GUID = v_guid
AND IFNULL(SPLIT_T.substring, '') <> ''
;
CALL demo.p_clear_split_temp( v_guid );
END IF;
IF v_has_filter_dog_name = 1 THEN
CALL demo.p_split(v_guid, a_names_dog, ',', a_debug);
INSERT INTO tmp_Split_Name (
substring
, as_int
)
SELECT
SPLIT_T.substring
, CONVERT(SPLIT_T.substring, DECIMAL(10,0)) AS as_int
FROM demo.CORE_Split_Temp SPLIT_T
WHERE
SPLIT_T.GUID = v_guid
AND IFNULL(SPLIT_T.substring, '') <> ''
;
CALL demo.p_clear_split_temp( v_guid );
END IF;
IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF EXISTS (
SELECT *
FROM tmp_Split_Id t_SPLIT_ID
LEFT JOIN demo.DOG_Dog DOG ON t_SPLIT_ID.as_int = DOG.id_dog
WHERE
ISNULL(t_SPLIT_ID.as_int)
OR ISNULL(DOG.id_dog)
OR (
DOG.active = 0
AND a_get_inactive_dog = 0
)
) THEN
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
v_id_type_error_bad_data
, v_code_type_error_bad_data
, CONCAT('Invalid or inactive Dog IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT_ID.substring SEPARATOR ', '), 'NULL'))
FROM tmp_Split_Id t_SPLIT_ID
LEFT JOIN demo.DOG_Dog DOG ON t_SPLIT_ID.as_int = DOG.id_dog
WHERE
ISNULL(t_SPLIT_ID.as_int)
OR ISNULL(DOG.id_dog)
OR (
DOG.active = 0
AND a_get_inactive_dog = 0
)
;
/* Don't error on names not found
ELSEIF EXISTS (
SELECT *
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(DOG.id_dog)
OR (
DOG.active = 0
AND a_get_inactive_dog = 0
)
) THEN
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
v_id_type_error_bad_data
, v_code_type_error_bad_data
, CONCAT('Invalid or inactive Dog IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL'))
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(DOG.id_dog)
OR (
DOG.active = 0
AND a_get_inactive_dog = 0
)
;
*/
ELSE
INSERT INTO tmp_Dog (
id_dog
, name
)
SELECT
DOG.id_dog
, DOG.name
FROM demo.DOG_Dog DOG
LEFT JOIN tmp_Split_Id t_SPLIT_ID ON DOG.id_dog = t_SPLIT_ID.as_int
LEFT JOIN tmp_Split_Name t_SPLIT_NAME ON DOG.name = t_SPLIT_NAME.substring
WHERE
(
a_get_all_dog = 1
OR (
v_has_filter_dog_id = 1
OR v_has_filter_dog_name = 1
)
)
AND (
a_get_inactive_dog = 1
OR DOG.active = 1
)
;
END IF;
END IF;
DELETE FROM tmp_Split_Id;
DELETE FROM tmp_Split_Name;
-- Permissions
IF a_debug = 1 THEN
SELECT
v_guid
, a_id_user
, FALSE -- a_get_inactive_user
, v_id_permission_dog_view
, 0 -- a_debug
;
END IF;
CALL demo.p_DOG_calc_user(
v_guid
, a_id_user
, FALSE -- a_get_inactive_user
, v_id_permission_dog_view
, 0 -- a_debug
);
SELECT
IFNULL(CALC_USER_T.has_access, 0)
INTO
v_can_view
FROM demo.DOG_Calc_User_Temp CALC_USER_T
WHERE CALC_USER_T.GUID = v_guid
LIMIT 1
;
IF a_debug = 1 THEN
SELECT v_can_view;
END IF;
IF (v_can_view = 0) THEN
DELETE t_ME
FROM tmp_Msg_Error t_ME
WHERE t_ME.id_type <> v_id_type_error_no_permission
;
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 view Commands.'
)
;
END IF;
CALL demo.p_DOG_clear_calc_user(
v_guid
, 0 -- a_debug
);
IF EXISTS(SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF a_debug = 1 THEN
SELECT * FROM tmp_Dog;
END IF;
DELETE FROM tmp_Dog;
END IF;
-- Outputs
-- Commands
SELECT
t_DOG.id_dog
, t_DOG.name
, DOG.appearance
, DOG.mass_kg
, DOG.notes
, DOG.active
FROM demo.DOG_Dog DOG
INNER JOIN tmp_Dog t_DOG ON DOG.id_dog = t_DOG.id_dog
;
-- Errors
SELECT
t_ERROR.id_error
, t_ERROR.id_type
, t_ERROR.code
, ERROR_TYPE.name
, ERROR_TYPE.description
, ERROR_TYPE.is_breaking_error
, ERROR_TYPE.background_colour
, ERROR_TYPE.text_colour
, t_ERROR.msg
FROM tmp_Msg_Error t_ERROR
INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type
;
IF a_debug = 1 AND v_can_view = 1 THEN
SELECT * FROM tmp_Dog;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp_Split_Name;
DROP TEMPORARY TABLE IF EXISTS tmp_Split_Id;
DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error;
DROP TEMPORARY TABLE IF EXISTS tmp_Dog;
IF a_debug = 1 THEN
CALL demo.p_core_debug_timing_reporting ( v_time_start );
END IF;
END //
DELIMITER ;
USE demo;
DROP PROCEDURE IF EXISTS demo.p_DOG_get_many_command;
DELIMITER //
CREATE PROCEDURE demo.p_DOG_get_many_command (
IN a_id_user INT
, IN a_get_all_command BIT
, IN a_get_inactive_command BIT
, IN a_ids_command TEXT
, IN a_names_command TEXT
, IN a_debug BIT
)
BEGIN
DECLARE v_code_type_error_bad_data VARCHAR(100);
DECLARE v_code_type_error_no_permission VARCHAR(100);
DECLARE v_id_type_error_bad_data INT;
DECLARE v_id_type_error_no_permission INT;
DECLARE v_has_filter_command_id BIT;
DECLARE v_has_filter_command_name BIT;
DECLARE v_guid BINARY(36);
DECLARE v_id_permission_command_view INT;
DECLARE v_id_minimum INT;
DECLARE v_time_start TIMESTAMP(6);
DECLARE v_can_view BIT;
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 (
id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT
, id_type INT NULL
, code VARCHAR(100) NOT NULL
, msg VARCHAR(4000) NOT NULL
);
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
MET.id_type
, @errno
, @text
FROM demo.CORE_Msg_Error_Type MET
WHERE MET.code = 'MYSQL_ERROR'
;
SELECT
t_ERROR.id_error
, t_ERROR.id_type
, t_ERROR.code
, ERROR_TYPE.name
, ERROR_TYPE.description
, ERROR_TYPE.is_breaking_error
, ERROR_TYPE.background_colour
, ERROR_TYPE.text_colour
, t_ERROR.msg
FROM tmp_Msg_Error t_ERROR
INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type
;
DROP TABLE IF EXISTS tmp_Msg_Error;
END;
SET v_time_start := CURRENT_TIMESTAMP(6);
SET v_guid := UUID();
SET v_code_type_error_bad_data := 'BAD_DATA';
SET v_code_type_error_no_permission := 'NO_PERMISSION';
SET v_id_type_error_bad_data := (SELECT ERROR_TYPE.id_type FROM demo.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_bad_data LIMIT 1);
SET v_id_type_error_no_permission := (SELECT ERROR_TYPE.id_type FROM demo.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_no_permission LIMIT 1);
SET v_id_permission_command_view := (SELECT PERMISSION.id_permission FROM demo.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_VIEW' LIMIT 1);
SET a_id_user := IFNULL(a_id_user, 0);
SET a_get_all_command := IFNULL(a_get_all_command, 0);
SET a_get_inactive_command := IFNULL(a_get_inactive_command, 0);
SET a_ids_command := TRIM(IFNULL(a_ids_command, ''));
SET a_names_command := TRIM(IFNULL(a_names_command, ''));
SET a_debug := IFNULL(a_debug, 0);
IF a_debug = 1 THEN
SELECT
a_id_user
, a_get_all_command
, a_get_inactive_command
, a_ids_command
, a_names_command
, a_debug
;
SELECT
v_id_type_error_bad_data
, v_id_type_error_no_permission
, v_guid
, v_id_permission_command_view
, v_time_start
;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp_Split_Name;
DROP TEMPORARY TABLE IF EXISTS tmp_Split_Id;
DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error;
DROP TEMPORARY TABLE IF EXISTS tmp_Command;
CREATE TEMPORARY TABLE tmp_Command (
id_command INT NOT NULL
, name VARCHAR(250)
);
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error (
id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT
, id_type INT NULL
, code VARCHAR(100) NOT NULL
, msg VARCHAR(4000) NOT NULL
);
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split_Id (
substring VARCHAR(4000) NOT NULL
, as_int INT NULL
);
DELETE FROM tmp_Split_Id;
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split_Name (
substring VARCHAR(4000) NOT NULL
, as_int INT NULL
);
DELETE FROM tmp_Split_Name;
CALL demo.p_core_validate_guid ( v_guid );
SET v_has_filter_command_id = CASE WHEN a_ids_command = '' THEN 0 ELSE 1 END;
SET v_has_filter_command_name = CASE WHEN a_names_command = '' THEN 0 ELSE 1 END;
-- Commands
IF v_has_filter_command_id = 1 THEN
CALL demo.p_split(v_guid, a_ids_command, ',', a_debug);
INSERT INTO tmp_Split_Id (
substring
, as_int
)
SELECT
SPLIT_T.substring
, CONVERT(SPLIT_T.substring, DECIMAL(10,0)) AS as_int
FROM demo.CORE_Split_Temp SPLIT_T
WHERE
SPLIT_T.GUID = v_guid
AND IFNULL(SPLIT_T.substring, '') <> ''
;
CALL demo.p_clear_split_temp( v_guid );
END IF;
IF v_has_filter_command_name = 1 THEN
CALL demo.p_split(v_guid, a_names_command, ',', a_debug);
INSERT INTO tmp_Split_Name (
substring
, as_int
)
SELECT
SPLIT_T.substring
, CONVERT(SPLIT_T.substring, DECIMAL(10,0)) AS as_int
FROM demo.CORE_Split_Temp SPLIT_T
WHERE
SPLIT_T.GUID = v_guid
AND IFNULL(SPLIT_T.substring, '') <> ''
;
CALL demo.p_clear_split_temp( v_guid );
END IF;
IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF EXISTS (
SELECT *
FROM tmp_Split_Id t_SPLIT_ID
LEFT JOIN demo.DOG_Command COMMAND ON t_SPLIT_ID.as_int = COMMAND.id_command
WHERE
ISNULL(t_SPLIT_ID.as_int)
OR ISNULL(COMMAND.id_command)
OR (
COMMAND.active = 0
AND a_get_inactive_command = 0
)
) THEN
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
v_id_type_error_bad_data
, v_code_type_error_bad_data
, CONCAT('Invalid or inactive Command IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT_ID.substring SEPARATOR ', '), 'NULL'))
FROM tmp_Split_Id t_SPLIT_ID
LEFT JOIN demo.DOG_Command COMMAND ON t_SPLIT_ID.as_int = COMMAND.id_command
WHERE
ISNULL(t_SPLIT_ID.as_int)
OR ISNULL(COMMAND.id_command)
OR (
COMMAND.active = 0
AND a_get_inactive_command = 0
)
;
/* Don't error on codes or names not found
ELSEIF EXISTS (
SELECT *
*/
ELSE
INSERT INTO tmp_Command (
id_command
, name
)
SELECT
COMMAND.id_command
, COMMAND.name
FROM demo.DOG_Command COMMAND
LEFT JOIN tmp_Split_Id t_SPLIT_ID ON COMMAND.id_command = t_SPLIT_ID.as_int
LEFT JOIN tmp_Split_Name t_SPLIT_NAME ON COMMAND.name = t_SPLIT_NAME.substring
WHERE
(
a_get_all_command = 1
OR (
v_has_filter_command_id = 1
OR v_has_filter_command_name = 1
)
)
AND (
a_get_inactive_command = 1
OR COMMAND.active = 1
)
;
END IF;
END IF;
DELETE FROM tmp_Split_Id;
DELETE FROM tmp_Split_Name;
-- Permissions
IF a_debug = 1 THEN
SELECT
v_guid
, a_id_user
, FALSE -- a_get_inactive_user
, v_id_permission_command_view
, 0 -- a_debug
;
END IF;
CALL demo.p_DOG_calc_user(
v_guid
, a_id_user
, FALSE -- a_get_inactive_user
, v_id_permission_command_view
, 0 -- a_debug
);
SELECT
IFNULL(CALC_USER_T.has_access, 0)
INTO
v_can_view
FROM demo.DOG_Calc_User_Temp CALC_USER_T
WHERE CALC_USER_T.GUID = v_guid
LIMIT 1
;
IF a_debug = 1 THEN
SELECT v_can_view;
END IF;
IF (v_can_view = 0) THEN
DELETE t_ME
FROM tmp_Msg_Error t_ME
WHERE t_ME.id_type <> v_id_type_error_no_permission
;
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 view Commands.'
)
;
END IF;
CALL demo.p_DOG_clear_calc_user(
v_guid
, 0 -- a_debug
);
IF EXISTS(SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF a_debug = 1 THEN
SELECT * FROM tmp_Command;
END IF;
DELETE FROM tmp_Command;
END IF;
-- Outputs
-- Commands
SELECT
t_COMMAND.id_command
, COMMAND.id_command_category
, t_COMMAND.name
, COMMAND.hand_signal_default_description
, COMMAND.can_have_button
, COMMAND.notes
, COMMAND.active
FROM demo.DOG_Command COMMAND
INNER JOIN tmp_Command t_COMMAND ON COMMAND.id_command = t_COMMAND.id_command
;
-- Errors
SELECT
t_ERROR.id_error
, t_ERROR.id_type
, t_ERROR.code
, ERROR_TYPE.name
, ERROR_TYPE.description
, ERROR_TYPE.is_breaking_error
, ERROR_TYPE.background_colour
, ERROR_TYPE.text_colour
, t_ERROR.msg
FROM tmp_Msg_Error t_ERROR
INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type
;
IF a_debug = 1 AND v_can_view = 1 THEN
SELECT * FROM tmp_Command;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp_Split_Name;
DROP TEMPORARY TABLE IF EXISTS tmp_Split_Id;
DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error;
DROP TEMPORARY TABLE IF EXISTS tmp_Command;
IF a_debug = 1 THEN
CALL demo.p_core_debug_timing_reporting ( v_time_start );
END IF;
END //
DELIMITER ;
CALL demo.p_DOG_get_many_dog (
1 -- 'auth0|6582b95c895d09a70ba10fef', -- a_id_user
, 1 -- a_get_all_dog
, 0 -- a_get_inactive_dog
, '' -- a_ids_dog
, '' -- a_names_dog
, 1 -- a_debug
);
CALL demo.p_DOG_get_many_command (
1 -- 'auth0|6582b95c895d09a70ba10fef', -- a_id_user
, 1 -- a_get_all_command
, 0 -- a_get_inactive_command
, '' -- a_ids_command
, '' -- a_names_command
, 1 -- a_debug
);

View File

@@ -14,13 +14,49 @@ DROP TABLE IF EXISTS parts.tmp_DOG_User_Role_Link;
-- Permanent Tables
DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link_Temp;
DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link_Audit;
DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link;
DROP TABLE IF EXISTS parts.DOG_Assessment_Response_Temp;
DROP TABLE IF EXISTS parts.DOG_Assessment_Response_Audit;
DROP TABLE IF EXISTS parts.DOG_Assessment_Response;
DROP TABLE IF EXISTS parts.DOG_Drive_Temp;
DROP TABLE IF EXISTS parts.DOG_Drive_Audit;
DROP TABLE IF EXISTS parts.DOG_Drive;
DROP TABLE IF EXISTS parts.DOG_Obedience_Level_Temp;
DROP TABLE IF EXISTS parts.DOG_Obedience_Level_Audit;
DROP TABLE IF EXISTS parts.DOG_Obedience_Level;
DROP TABLE IF EXISTS parts.DOG_Response_Quality_Metric_Temp;
DROP TABLE IF EXISTS parts.DOG_Response_Quality_Metric_Audit;
DROP TABLE IF EXISTS parts.DOG_Response_Quality_Metric;
DROP TABLE IF EXISTS parts.DOG_Assessment_Command_Modality_Link_Temp;
DROP TABLE IF EXISTS parts.DOG_Assessment_Command_Modality_Link_Audit;
DROP TABLE IF EXISTS parts.DOG_Assessment_Command_Modality_Link;
DROP TABLE IF EXISTS parts.DOG_Bribe_Temp;
DROP TABLE IF EXISTS parts.DOG_Bribe_Audit;
DROP TABLE IF EXISTS parts.DOG_Bribe;
DROP TABLE IF EXISTS parts.DOG_Distraction_Temp;
DROP TABLE IF EXISTS parts.DOG_Distraction_Audit;
DROP TABLE IF EXISTS parts.DOG_Distraction;
DROP TABLE IF EXISTS parts.DOG_Distraction_Intensity_Level_Temp;
DROP TABLE IF EXISTS parts.DOG_Distraction_Intensity_Level_Audit;
DROP TABLE IF EXISTS parts.DOG_Distraction_Intensity_Level;
DROP TABLE IF EXISTS parts.DOG_Distraction_Type_Temp;
DROP TABLE IF EXISTS parts.DOG_Distraction_Type_Audit;
DROP TABLE IF EXISTS parts.DOG_Distraction_Type;
DROP TABLE IF EXISTS parts.DOG_Assessment_Temp;
DROP TABLE IF EXISTS parts.DOG_Assessment_Audit;
DROP TABLE IF EXISTS parts.DOG_Assessment;
DROP TABLE IF EXISTS parts.DOG_Lighting_Level_Temp;
DROP TABLE IF EXISTS parts.DOG_Lighting_Level_Audit;
DROP TABLE IF EXISTS parts.DOG_Lighting_Level;
DROP TABLE IF EXISTS parts.DOG_Weather_Temp;
DROP TABLE IF EXISTS parts.DOG_Weather_Audit;
DROP TABLE IF EXISTS parts.DOG_Weather;
DROP TABLE IF EXISTS parts.DOG_Command_Button_Link_Temp;
DROP TABLE IF EXISTS parts.DOG_Command_Button_Link_Audit;
@@ -34,14 +70,14 @@ DROP TABLE IF EXISTS parts.DOG_Image_Temp;
DROP TABLE IF EXISTS parts.DOG_Image_Audit;
DROP TABLE IF EXISTS parts.DOG_Image;
DROP TABLE IF EXISTS parts.DOG_Button_Shape_Temp;
DROP TABLE IF EXISTS parts.DOG_Button_Shape_Audit;
DROP TABLE IF EXISTS parts.DOG_Button_Shape;
DROP TABLE IF EXISTS parts.DOG_Colour_Temp;
DROP TABLE IF EXISTS parts.DOG_Colour_Audit;
DROP TABLE IF EXISTS parts.DOG_Colour;
DROP TABLE IF EXISTS parts.DOG_Button_Shape_Temp;
DROP TABLE IF EXISTS parts.DOG_Button_Shape_Audit;
DROP TABLE IF EXISTS parts.DOG_Button_Shape;
DROP TABLE IF EXISTS parts.DOG_Location_Link_Temp;
DROP TABLE IF EXISTS parts.DOG_Location_Link_Audit;
DROP TABLE IF EXISTS parts.DOG_Location_Link;
@@ -50,9 +86,15 @@ DROP TABLE IF EXISTS parts.DOG_Location_Temp;
DROP TABLE IF EXISTS parts.DOG_Location_Audit;
DROP TABLE IF EXISTS parts.DOG_Location;
DROP TABLE IF EXISTS parts.DOG_Command_Modality_Temp;
DROP TABLE IF EXISTS parts.DOG_Command_Modality_Audit;
DROP TABLE IF EXISTS parts.DOG_Command_Modality;
/* Start of remove section */
DROP TABLE IF EXISTS parts.DOG_Personal_Best_Temp;
DROP TABLE IF EXISTS parts.DOG_Personal_Best_Audit;
DROP TABLE IF EXISTS parts.DOG_Personal_Best;
/* End of remove section */
DROP TABLE IF EXISTS parts.DOG_Dog_Command_Link_Temp;
DROP TABLE IF EXISTS parts.DOG_Dog_Command_Link_Audit;
@@ -66,10 +108,7 @@ DROP TABLE IF EXISTS parts.DOG_Command_Category_Temp;
DROP TABLE IF EXISTS parts.DOG_Command_Category_Audit;
DROP TABLE IF EXISTS parts.DOG_Command_Category;
DROP TABLE IF EXISTS parts.DOG_Obedience_Level_Temp;
DROP TABLE IF EXISTS parts.DOG_Obedience_Level_Audit;
DROP TABLE IF EXISTS parts.DOG_Obedience_Level;
/* Start of remove section */
DROP TABLE IF EXISTS parts.DOG_Understanding_Level_Temp;
DROP TABLE IF EXISTS parts.DOG_Understanding_Level_Audit;
DROP TABLE IF EXISTS parts.DOG_Understanding_Level;
@@ -77,6 +116,15 @@ DROP TABLE IF EXISTS parts.DOG_Understanding_Level;
DROP TABLE IF EXISTS parts.DOG_Competency_Level_Temp;
DROP TABLE IF EXISTS parts.DOG_Competency_Level_Audit;
DROP TABLE IF EXISTS parts.DOG_Competency_Level;
/* End of remove section */
DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link_Temp;
DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link_Audit;
DROP TABLE IF EXISTS parts.DOG_Dog_Drive_Link;
DROP TABLE IF EXISTS parts.DOG_Drive_Temp;
DROP TABLE IF EXISTS parts.DOG_Drive_Audit;
DROP TABLE IF EXISTS parts.DOG_Drive;
DROP TABLE IF EXISTS parts.DOG_Dog_Breed_Link_Temp;
DROP TABLE IF EXISTS parts.DOG_Dog_Breed_Link_Audit;
@@ -92,6 +140,13 @@ DROP TABLE IF EXISTS parts.DOG_Dog;
DROP TABLE IF EXISTS parts.DOG_Dog_Change_Set;
-- Core tables
DROP TABLE IF EXISTS parts.DOG_Unit_Measurement_Conversion_Audit;
DROP TABLE IF EXISTS parts.DOG_Unit_Measurement_Conversion;
DROP TABLE IF EXISTS parts.DOG_Unit_Measurement_Audit;
DROP TABLE IF EXISTS parts.DOG_Unit_Measurement;
DROP TABLE IF EXISTS parts.DOG_Calc_User_Temp;
DROP TABLE IF EXISTS parts.DOG_User_Role_Link_Audit;
@@ -118,11 +173,10 @@ DROP TABLE IF EXISTS parts.DOG_Access_Level;
DROP TABLE IF EXISTS parts.DOG_User_Change_Set;
/*
DROP TABLE IF EXISTS parts.CORE_Split_Key_Value_Pair_Csv_Temp;
DROP TABLE IF EXISTS parts.CORE_Split_Temp;
*/
DROP TABLE IF EXISTS parts.CORE_File_Type;
DROP TABLE IF EXISTS parts.CORE_Msg_Error_Type;
@@ -130,6 +184,8 @@ DROP TABLE IF EXISTS parts.CORE_Msg_Error_Type;
DROP PROCEDURE IF EXISTS parts.p_DOG_test_get_many_dog_command;
DROP PROCEDURE IF EXISTS parts.p_DOG_test_get_many_command;
DROP PROCEDURE IF EXISTS parts.p_DOG_get_many_command;
DROP PROCEDURE IF EXISTS parts.p_DOG_get_many_dog_command;
DROP PROCEDURE IF EXISTS parts.p_DOG_get_many_dog_command_link;
DROP PROCEDURE IF EXISTS parts.p_DOG_test_save_command;
DROP PROCEDURE IF EXISTS parts.p_DOG_save_command;

View File

@@ -1,672 +0,0 @@
USE demo;
DROP PROCEDURE IF EXISTS demo.p_DOG_get_many_dog_command;
DELIMITER //
CREATE PROCEDURE demo.p_DOG_get_many_dog_command (
IN a_id_user INT
, IN a_get_all_dog BIT
, IN a_get_inactive_dog BIT
, IN a_ids_dog TEXT
, IN a_get_all_command BIT
, IN a_get_inactive_command BIT
, IN a_ids_command TEXT
, IN a_get_all_understanding_level BIT
, IN a_get_inactive_understanding_level BIT
, IN a_ids_understanding_level TEXT
, IN a_get_all_obedience_level BIT
, IN a_get_inactive_obedience_level BIT
, IN a_ids_obedience_level TEXT
, IN a_debug BIT
)
BEGIN
DECLARE v_code_type_error_bad_data VARCHAR(100);
DECLARE v_code_type_error_no_permission VARCHAR(100);
DECLARE v_id_type_error_bad_data INT;
DECLARE v_id_type_error_no_permission INT;
DECLARE v_has_filter_command BIT;
DECLARE v_has_filter_dog BIT;
DECLARE v_has_filter_obedience_level BIT;
DECLARE v_has_filter_understanding_level BIT;
DECLARE v_guid BINARY(36);
DECLARE v_id_permission_dog_view INT;
DECLARE v_id_minimum INT;
DECLARE v_time_start TIMESTAMP(6);
DECLARE v_can_view BIT;
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 (
id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT
, id_type INT NULL
, code VARCHAR(100) NOT NULL
, msg VARCHAR(4000) NOT NULL
);
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
MET.id_type
, @errno
, @text
FROM demo.CORE_Msg_Error_Type MET
WHERE MET.code = 'MYSQL_ERROR'
;
SELECT
t_ERROR.id_error
, t_ERROR.id_type
, t_ERROR.code
, ERROR_TYPE.name
, ERROR_TYPE.description
, ERROR_TYPE.is_breaking_error
, ERROR_TYPE.background_colour
, ERROR_TYPE.text_colour
, t_ERROR.msg
FROM tmp_Msg_Error t_ERROR
INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type
;
DROP TABLE IF EXISTS tmp_Msg_Error;
END;
SET v_time_start := CURRENT_TIMESTAMP(6);
SET v_guid := UUID();
SET v_code_type_error_bad_data := 'BAD_DATA';
SET v_code_type_error_no_permission := 'NO_PERMISSION';
SET v_id_type_error_bad_data := (SELECT ERROR_TYPE.id_type FROM demo.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_bad_data LIMIT 1);
SET v_id_type_error_no_permission := (SELECT ERROR_TYPE.id_type FROM demo.CORE_Msg_Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = v_code_type_error_no_permission LIMIT 1);
SET v_id_permission_dog_view := (SELECT PERMISSION.id_permission FROM demo.DOG_Permission PERMISSION WHERE PERMISSION.code = 'DOG_VIEW' LIMIT 1);
SET a_id_user := IFNULL(a_id_user, 0);
SET a_get_all_dog := IFNULL(a_get_all_dog, 0);
SET a_get_inactive_dog := IFNULL(a_get_inactive_dog, 0);
SET a_ids_dog := TRIM(IFNULL(a_ids_dog, ''));
SET a_get_all_command := IFNULL(a_get_all_command, 0);
SET a_get_inactive_command := IFNULL(a_get_inactive_command, 0);
SET a_ids_command := TRIM(IFNULL(a_ids_command, ''));
SET a_get_all_understanding_level := IFNULL(a_get_all_understanding_level, 0);
SET a_get_inactive_understanding_level := IFNULL(a_get_inactive_understanding_level, 0);
SET a_ids_understanding_level := TRIM(IFNULL(a_ids_understanding_level, ''));
SET a_get_all_obedience_level := IFNULL(a_get_all_obedience_level, 0);
SET a_get_inactive_obedience_level := IFNULL(a_get_inactive_obedience_level, 0);
SET a_ids_obedience_level := TRIM(IFNULL(a_ids_obedience_level, ''));
SET a_debug := IFNULL(a_debug, 0);
IF a_debug = 1 THEN
SELECT
a_id_user
, a_get_all_dog
, a_get_inactive_dog
, a_ids_dog
, a_get_all_command
, a_get_inactive_command
, a_ids_command
, a_get_all_understanding_level
, a_get_inactive_understanding_level
, a_ids_understanding_level
, a_get_all_obedience_level
, a_get_inactive_obedience_level
, a_ids_obedience_level
, a_debug
;
SELECT
v_id_type_error_bad_data
, v_id_type_error_no_permission
, v_guid
, v_id_permission_dog_view
, v_time_start
;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp_Split;
DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error;
DROP TEMPORARY TABLE IF EXISTS tmp_Obedience_Level;
DROP TEMPORARY TABLE IF EXISTS tmp_Understanding_Level;
DROP TEMPORARY TABLE IF EXISTS tmp_Command;
DROP TEMPORARY TABLE IF EXISTS tmp_Dog;
CREATE TEMPORARY TABLE tmp_Dog (
id_dog INT NOT NULL
, name VARCHAR(250)
);
CREATE TEMPORARY TABLE tmp_Command (
id_command INT NOT NULL
, id_command_category INT NOT NULL
, name_command_category VARCHAR(250)
, has_button
-- , code VARCHAR(100)
, name VARCHAR(250)
);
CREATE TEMPORARY TABLE tmp_Understanding_Level (
id_understanding_level INT NOT NULL
, code VARCHAR(100)
, name VARCHAR(250)
);
CREATE TEMPORARY TABLE tmp_Obedience_Level (
id_obedience_level INT NOT NULL
, code VARCHAR(100)
, name VARCHAR(250)
);
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error (
id_error INT NOT NULL PRIMARY KEY AUTO_INCREMENT
, id_type INT NULL
, code VARCHAR(100) NOT NULL
, msg VARCHAR(4000) NOT NULL
);
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split (
substring VARCHAR(4000) NOT NULL
, as_int INT NULL
);
DELETE FROM tmp_Split;
CALL demo.p_core_validate_guid ( v_guid );
SET v_has_filter_dog = CASE WHEN a_ids_dog = '' THEN 0 ELSE 1 END;
SET v_has_filter_command = CASE WHEN a_ids_command = '' THEN 0 ELSE 1 END;
SET v_has_filter_understanding_level = CASE WHEN a_ids_understanding_level = '' THEN 0 ELSE 1 END;
SET v_has_filter_obedience_level = CASE WHEN a_ids_obedience_level = '' THEN 0 ELSE 1 END;
-- Dogs
IF v_has_filter_dog = 1 THEN
CALL demo.p_split(v_guid, a_ids_dog, ',', a_debug);
INSERT INTO tmp_Split (
substring
, as_int
)
SELECT
SPLIT_T.substring
, CONVERT(SPLIT_T.substring, DECIMAL(10,0)) AS as_int
FROM demo.CORE_Split_Temp SPLIT_T
WHERE
SPLIT_T.GUID = v_guid
AND IFNULL(SPLIT_T.substring, '') <> ''
;
CALL demo.p_clear_split_temp( v_guid );
END IF;
IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF EXISTS (
SELECT *
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(DOG.id_dog)
OR (
DOG.active = 0
AND a_get_inactive_dog = 0
)
) THEN
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
v_id_type_error_bad_data
, v_code_type_error_bad_data
, CONCAT('Invalid or inactive Dog IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL'))
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(DOG.id_dog)
OR (
DOG.active = 0
AND a_get_inactive_dog = 0
)
;
ELSE
INSERT INTO tmp_Dog (
id_dog
, name
)
SELECT
DOG.id_dog
, DOG.name
FROM tmp_Split t_SPLIT
RIGHT JOIN demo.DOG_Dog DOG ON t_SPLIT.as_int = DOG.id_dog
WHERE
(
a_get_all_dog = 1
OR (
v_has_filter_dog = 1
AND NOT ISNULL(t_SPLIT.as_int)
)
)
AND (
a_get_inactive_dog = 1
OR DOG.active = 1
)
;
END IF;
END IF;
DELETE FROM tmp_Split;
-- Commands
IF v_has_filter_command = 1 THEN
CALL demo.p_split(v_guid, a_ids_command, ',', a_debug);
INSERT INTO tmp_Split (
substring
, as_int
)
SELECT
substring
, CONVERT(substring, DECIMAL(10,0)) AS as_int
FROM demo.CORE_Split_Temp
WHERE
GUID = v_guid
AND NOT ISNULL(substring)
AND substring <> ''
;
CALL demo.p_clear_split_temp( v_guid );
END IF;
IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF EXISTS (
SELECT *
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(COMMAND.id_command)
OR (
COMMAND.active = 0
AND a_get_inactive_command = 0
)
) THEN
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
v_id_type_error_bad_data
, v_code_type_error_bad_data
, CONCAT('Invalid or inactive Command IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL'))
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(COMMAND.id_command)
OR (
COMMAND.active = 0
AND a_get_inactive_command = 0
)
;
ELSE
INSERT INTO tmp_Command (
id_command
, id_command_category
, name_command_category
, name
)
SELECT
COMMAND.id_command
, COMMAND.id_command_category
, COMMAND_CATEGORY.name AS name_command_category
-- , COMMAND.code
, COMMAND.name
FROM tmp_Split t_SPLIT
RIGHT JOIN demo.DOG_Command COMMAND ON t_SPLIT.as_int = COMMAND.id_command
LEFT JOIN demo.DOG_Command_Category COMMAND_CATEGORY ON COMMAND.id_command_category = COMMAND_CATEGORY.id_command_category
WHERE
(
a_get_all_command = 1
OR (
v_has_filter_command = 1
AND NOT ISNULL(t_SPLIT.as_int)
)
)
AND (
a_get_inactive_command = 1
OR COMMAND.active = 1
)
;
END IF;
END IF;
DELETE FROM tmp_Split;
-- Understanding Levels
IF v_has_filter_understanding_level = 1 THEN
CALL demo.p_split(v_guid, a_ids_understanding_level, ',', a_debug);
INSERT INTO tmp_Split (
substring
, as_int
)
SELECT
substring
, CONVERT(substring, DECIMAL(10,0)) AS as_int
FROM demo.CORE_Split_Temp
WHERE
GUID = v_guid
AND NOT ISNULL(substring)
AND substring <> ''
;
CALL demo.p_clear_split_temp( v_guid );
END IF;
IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF EXISTS (
SELECT *
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(UNDERSTANDING_LEVEL.id_understanding_level)
OR (
UNDERSTANDING_LEVEL.active = 0
AND a_get_inactive_understanding_level = 0
)
) THEN
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
v_id_type_error_bad_data
, v_code_type_error_bad_data
, CONCAT('Invalid or inactive Understanding Level IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL'))
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(UNDERSTANDING_LEVEL.id_understanding_level)
OR (
UNDERSTANDING_LEVEL.active = 0
AND a_get_inactive_understanding_level = 0
)
;
ELSE
INSERT INTO tmp_Understanding_Level (
id_understanding_level
, code
, name
)
SELECT
UNDERSTANDING_LEVEL.id_understanding_level
, UNDERSTANDING_LEVEL.code
, UNDERSTANDING_LEVEL.name
FROM tmp_Split t_SPLIT
RIGHT JOIN demo.DOG_Understanding_Level UNDERSTANDING_LEVEL ON t_SPLIT.as_int = UNDERSTANDING_LEVEL.id_understanding_level
WHERE
(
a_get_all_understanding_level = 1
OR (
v_has_filter_understanding_level = 1
AND NOT ISNULL(t_SPLIT.as_int)
)
)
AND (
a_get_inactive_understanding_level = 1
OR UNDERSTANDING_LEVEL.active = 1
)
;
END IF;
END IF;
DELETE FROM tmp_Split;
-- Obedience Levels
IF v_has_filter_obedience_level = 1 THEN
CALL demo.p_split(v_guid, a_ids_obedience_level, ',', a_debug);
INSERT INTO tmp_Split (
substring
, as_int
)
SELECT
substring
, CONVERT(substring, DECIMAL(10,0)) AS as_int
FROM demo.CORE_Split_Temp
WHERE
GUID = v_guid
AND NOT ISNULL(substring)
AND substring <> ''
;
CALL demo.p_clear_split_temp( v_guid );
END IF;
IF NOT EXISTS (SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF EXISTS (
SELECT *
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(OBEDIENCE_LEVEL.id_obedience_level)
OR (
OBEDIENCE_LEVEL.active = 0
AND a_get_inactive_obedience_level = 0
)
) THEN
INSERT INTO tmp_Msg_Error (
id_type
, code
, msg
)
SELECT
v_id_type_error_bad_data
, v_code_type_error_bad_data
, CONCAT('Invalid or inactive Obedience Level IDs: ', IFNULL(GROUP_CONCAT(t_SPLIT.substring SEPARATOR ', '), 'NULL'))
FROM tmp_Split t_SPLIT
LEFT JOIN demo.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level
WHERE
ISNULL(t_SPLIT.as_int)
OR ISNULL(OBEDIENCE_LEVEL.id_obedience_level)
OR (
OBEDIENCE_LEVEL.active = 0
AND a_get_inactive_obedience_level = 0
)
;
ELSE
INSERT INTO tmp_Obedience_Level (
id_obedience_level
, code
, name
)
SELECT
OBEDIENCE_LEVEL.id_obedience_level
, OBEDIENCE_LEVEL.code
, OBEDIENCE_LEVEL.name
FROM tmp_Split t_SPLIT
RIGHT JOIN demo.DOG_Obedience_Level OBEDIENCE_LEVEL ON t_SPLIT.as_int = OBEDIENCE_LEVEL.id_obedience_level
WHERE
(
a_get_all_obedience_level = 1
OR (
v_has_filter_obedience_level = 1
AND NOT ISNULL(t_SPLIT.as_int)
)
)
AND (
a_get_inactive_obedience_level = 1
OR OBEDIENCE_LEVEL.active = 1
)
;
END IF;
END IF;
DELETE FROM tmp_Split;
-- Permissions
IF a_debug = 1 THEN
SELECT
v_guid
, a_id_user
, FALSE -- a_get_inactive_user
, v_id_permission_dog_view
, 0 -- a_debug
;
END IF;
CALL demo.p_DOG_calc_user(
v_guid
, a_id_user
, FALSE -- a_get_inactive_user
, v_id_permission_dog_view
, 0 -- a_debug
);
SELECT
IFNULL(CALC_USER_T.has_access, 0)
INTO
v_can_view
FROM demo.DOG_Calc_User_Temp CALC_USER_T
WHERE CALC_USER_T.GUID = v_guid
LIMIT 1
;
IF a_debug = 1 THEN
SELECT v_can_view;
END IF;
IF (v_can_view = 0) THEN
DELETE t_ME
FROM tmp_Msg_Error t_ME
WHERE t_ME.id_type <> v_id_type_error_no_permission
;
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 view Commands.'
)
;
END IF;
CALL demo.p_DOG_clear_calc_user(
v_guid
, 0 -- a_debug
);
IF EXISTS(SELECT * FROM tmp_Msg_Error t_ERROR INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type WHERE ERROR_TYPE.is_breaking_error = 1 LIMIT 1) THEN
IF a_debug = 1 THEN
SELECT * FROM tmp_Dog;
SELECT * FROM tmp_Command;
SELECT * FROM tmp_Obedience_Level;
END IF;
DELETE FROM tmp_Dog;
DELETE FROM tmp_Command;
SELECT * FROM tmp_Understanding_Level;
DELETE FROM tmp_Obedience_Level;
END IF;
-- Outputs
-- Commands
SELECT
DOG_COMMAND_LINK.id_link AS id_dog_command_link
, t_DOG.id_dog
, t_DOG.name AS name_dog
, t_COMMAND.id_command_category
, t_COMMAND.name_command_category
, t_COMMAND.id_command
-- , t_COMMAND.code
, t_COMMAND.name AS name_command
, t_UNDERSTANDING_LEVEL.id_understanding_level
, t_UNDERSTANDING_LEVEL.code AS code_understanding_level
, t_UNDERSTANDING_LEVEL.name AS name_understanding_level
, t_OBEDIENCE_LEVEL.id_obedience_level
, t_OBEDIENCE_LEVEL.code AS code_obedience_level
, t_OBEDIENCE_LEVEL.name AS name_obedience_level
, DOG_COMMAND_LINK.hand_signal_description
, DOG_COMMAND_LINK.notes
, DOG_COMMAND_LINK.active
FROM demo.DOG_Dog_Command_Link DOG_COMMAND_LINK
INNER JOIN tmp_Dog t_DOG ON DOG_COMMAND_LINK.id_dog = t_DOG.id_dog
INNER JOIN tmp_Command t_COMMAND ON DOG_COMMAND_LINK.id_command = t_COMMAND.id_command
INNER JOIN tmp_Understanding_Level t_UNDERSTANDING_LEVEL ON DOG_COMMAND_LINK.id_understanding_level = t_UNDERSTANDING_LEVEL.id_understanding_level
INNER JOIN tmp_Obedience_Level t_OBEDIENCE_LEVEL ON DOG_COMMAND_LINK.id_obedience_level = t_OBEDIENCE_LEVEL.id_obedience_level
;
-- Errors
SELECT
t_ERROR.id_error
, t_ERROR.id_type
, t_ERROR.code
, ERROR_TYPE.name
, ERROR_TYPE.description
, ERROR_TYPE.is_breaking_error
, ERROR_TYPE.background_colour
, ERROR_TYPE.text_colour
, t_ERROR.msg
FROM tmp_Msg_Error t_ERROR
INNER JOIN demo.CORE_Msg_Error_Type ERROR_TYPE ON t_ERROR.id_type = ERROR_TYPE.id_type
;
IF a_debug = 1 AND v_can_view = 1 THEN
SELECT * FROM tmp_Dog;
SELECT * FROM tmp_Command;
SELECT * FROM tmp_Understanding_Level;
SELECT * FROM tmp_Obedience_Level;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp_Split;
DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error;
DROP TEMPORARY TABLE IF EXISTS tmp_Obedience_Level;
DROP TEMPORARY TABLE IF EXISTS tmp_Understanding_Level;
DROP TEMPORARY TABLE IF EXISTS tmp_Command;
DROP TEMPORARY TABLE IF EXISTS tmp_Dog;
IF a_debug = 1 THEN
CALL demo.p_core_debug_timing_reporting ( v_time_start );
END IF;
END //
DELIMITER ;
/*
CALL demo.p_DOG_get_many_dog_command (
1 -- 'auth0|6582b95c895d09a70ba10fef', -- a_id_user
, 1 -- a_get_all_dog
, 0 -- a_get_inactive_dog
, '' -- a_ids_dog
, 1 -- a_get_all_command
, 0 -- a_get_inactive_command
, '' -- a_ids_command
, 1 -- a_get_all_understanding_level
, 0 -- a_get_inactive_understanding_level
, '' -- a_ids_understanding_level
, 1 -- a_get_all_obedience_level
, 0 -- a_get_inactive_obedience_level
, '' -- a_ids_obedience_level
, 1 -- a_debug
);
*/

View File

@@ -0,0 +1,25 @@
# Unit of Measurement
USE parts;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'parts'
AND TABLE_NAME = 'DOG_Unit_Measurement'
;
CREATE TABLE IF NOT EXISTS DOG_Unit_Measurement (
id_unit_measurement INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, name_singular VARCHAR(255) NOT NULL
, name_plural VARCHAR(256) NOT NULL
, symbol VARCHAR(50) NOT NULL
, symbol_is_suffix_not_prefix BIT NOT NULL DEFAULT 1
, is_base_unit BIT NOT NULL DEFAULT 0
, is_unit_of_distance BIT NOT NULL DEFAULT 0
, is_unit_of_mass BIT NOT NULL DEFAULT 0
, is_unit_of_time BIT NOT NULL DEFAULT 0
, is_unit_of_volume BIT NOT NULL DEFAULT 0
, active BIT NOT NULL DEFAULT 1
);

View File

@@ -0,0 +1,22 @@
# Unit of Measurement Conversion
USE parts;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'parts'
AND TABLE_NAME = 'DOG_Unit_Measurement_Conversion'
;
CREATE TABLE IF NOT EXISTS DOG_Unit_Measurement_Conversion (
id_conversion INT NOT NULL PRIMARY KEY AUTO_INCREMENT
, id_unit_derived INT NOT NULL
, id_unit_base INT NOT NULL
, multiplier_unit_base FLOAT NOT NULL
, increment_unit_base FLOAT NOT NULL
, apply_multiplier_before_increment BIT NOT NULL DEFAULT 1
, active BIT NOT NULL DEFAULT 1
, display_order INT NOT NULL
);

View File

@@ -18,6 +18,7 @@ CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link (
, CONSTRAINT FK_DOG_Dog_Command_Link_id_command
FOREIGN KEY (id_command)
REFERENCES parts.DOG_Command(id_command)
/*
, id_understanding_level INT NOT NULL
, CONSTRAINT FK_DOG_Dog_Command_Link_id_understanding_level
FOREIGN KEY (id_understanding_level)
@@ -26,6 +27,7 @@ CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link (
, CONSTRAINT FK_DOG_Dog_Command_Link_id_obedience_level
FOREIGN KEY (id_obedience_level)
REFERENCES parts.DOG_Obedience_Level(id_obedience_level)
*/
, hand_signal_description TEXT
, notes TEXT
-- , has_button BIT NOT NULL DEFAULT 0

View File

@@ -13,8 +13,10 @@ CREATE TABLE IF NOT EXISTS parts.DOG_Dog_Command_Link_Temp (
, id_link INT
, id_dog INT
, id_command INT
/*
, id_understanding_level INT
, id_obedience_level INT
*/
, hand_signal_description TEXT
, notes TEXT
-- , has_button BIT

View File

@@ -0,0 +1,25 @@
USE parts;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'parts'
AND TABLE_NAME = 'DOG_Command_Modality'
;
CREATE TABLE IF NOT EXISTS parts.DOG_Command_Modality (
id_command_modality INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, code VARCHAR(100) NOT NULL
, name VARCHAR(250) NOT NULL
, active BIT NOT NULL DEFAULT 1
, created_on DATETIME
, id_user_created_by INT
, CONSTRAINT FK_DOG_Command_Modality_id_user_created_by
FOREIGN KEY (id_user_created_by)
REFERENCES parts.DOG_User(id_user)
, id_change_set INT
, CONSTRAINT FK_DOG_Command_Modality_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES parts.DOG_Dog_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,24 @@
USE parts;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'parts'
AND TABLE_NAME = 'DOG_Command_Modality_Audit'
;
CREATE TABLE IF NOT EXISTS parts.DOG_Command_Modality_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_command_modality INT NOT NULL
, CONSTRAINT FK_DOG_Command_Modality_Audit_id_command_modality
FOREIGN KEY (id_command_modality)
REFERENCES parts.DOG_Command_Modality(id_command_modality)
, name_field VARCHAR(100) NOT NULL
, value_prev TEXT
, value_new TEXT
, id_change_set INT NOT NULL
, CONSTRAINT FK_DOG_Command_Modality_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES parts.DOG_Dog_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,18 @@
USE parts;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'parts'
AND TABLE_NAME = 'DOG_Command_Modality_Temp'
;
CREATE TABLE IF NOT EXISTS parts.DOG_Command_Modality_Temp (
id_temp INT NOT NULL PRIMARY KEY AUTO_INCREMENT
, id_command_modality INT
, code VARCHAR(100)
, name VARCHAR(250)
, active BIT
, guid BINARY(36)
);

Some files were not shown because too many files have changed in this diff Show More