21 Commits

Author SHA1 Message Date
3a8799058e Fix(Backend): Correct receive_marketing_communications form boolean field output to database. 2025-03-21 11:45:33 +00:00
8485b8a24d Fix(Backend): Correct bad python imports. 2025-03-21 11:29:09 +00:00
4f5037b504 Feat: Contact Form MySQL database created and hooked up to web app on form submission. \n Fix: Removal of ERP and otherwise deprecated database and server code.. 2025-03-21 11:12:03 +00:00
63776954e1 Fix(UI): Contact Us page styling for receive-marketing checkbox and CAPTCHA. 2025-03-16 18:59:46 +00:00
dd608022cd Feat: \n 1. Contact Us page form submission success page created. \n 2. Contact Us page styling and CAPTCHA text content. \n 3. Removal of ERP, Google CAPTCHA, and ALTCHA API code and left over comments in JavaScript, Python. 2025-03-16 16:56:15 +00:00
4add7e626e Fix: ALTCHA secret key missing error. 2025-03-15 18:41:14 +00:00
1a7b72022d Fix: ALTCHA secret key not found. 2025-03-15 18:34:13 +00:00
90cf9eaee7 Fix: ALTCHA create challenge error. 2025-03-15 19:32:34 +01:00
Teddy-1024
7b9e900cfe Merge pull request #4 from Teddy-1024/root_server
Root server
2025-03-15 17:59:03 +00:00
bade1f11dd Feat: Update CAPTCHA service to ALTCHA self-hosted. 2025-03-15 17:47:36 +00:00
b843849af9 Feat: Replace Google ReCAPTCHA with ALTCHA using API - non-tracking, GDPR compliant without cookies or fingerprinting. 2025-03-13 15:36:41 +00:00
29205de12f Fix(UI): Home page: improved content for all sections, including new CTAs for buttons. 2025-01-25 18:10:17 +00:00
a105372638 Fix(UI): Home page: improved content for all sections, including new CTAs for buttons. 2025-01-25 18:07:27 +00:00
7e8266d735 Fix: Run NPM build. 2025-01-25 16:59:47 +00:00
cc6c3699f6 Fix(UI): Contact form reCAPTCHA style correction for extreme zooming. 2025-01-25 16:55:19 +00:00
d84cc29edb Fix: Re-add requirements.txt after accidental delete in merging. 2025-01-25 16:27:13 +00:00
Teddy-1024
2fcd7f4276 Merge pull request #3 from Teddy-1024/oracle_vps
Feat(Security):  a. Update CORS settings  b. Update session cookie settings  c. Remove comments that expose project architecture (and that Claude made most of it :P) d. Remove server console logging from root server setup.
2025-01-25 16:10:02 +00:00
56ed26b3f0 Merge conflicts. 2025-01-25 16:07:58 +00:00
18a9a65f70 Merge conflicts. 2025-01-25 16:06:55 +00:00
Teddy-1024
d07f409426 Merge conflic: Update app.py 2025-01-25 16:05:07 +00:00
baa158fcd0 Feat(Security):
a. Update CORS settings
 b. Update session cookie settings
 c. Remove comments that expose project architecture (and that Claude made most of it :P)
2025-01-25 14:31:03 +00:00
540 changed files with 11265 additions and 106754 deletions

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@ __pycache__/
# Ignore logs and databases
*.log
*.log.*
# Ignore logs and databases
# *.sql

42
app.py
View File

@@ -17,10 +17,10 @@ Initializes the Flask application, sets the configuration based on the environme
# IMPORTS
# internal
from config import app_config, Config
from controllers.core import routes_core
from controllers.legal import routes_legal
from controllers.user import routes_user
from extensions import db, csrf, cors, mail, oauth
from controllers.core.contact import routes_core_contact
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
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session
@@ -48,13 +48,6 @@ app.config.from_object(app_config) # for db init with required keys
app.app_config = app_config
# app.config["config"] = app_config()
print('sql vars')
print(app.config['DB_PASSWORD'])
print(app.config['DB_USER'])
print(app.config['SQLALCHEMY_DATABASE_URI'])
print(app.config['SECRET_KEY'])
print(os.getenv('KEY_SECRET_FLASK'))
# logging
handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=3)
handler.setLevel(logging.DEBUG)
@@ -81,12 +74,13 @@ def make_session_permanent():
session.permanent = True
csrf = CSRFProtect()
"""
cors = CORS()
db = SQLAlchemy()
mail = Mail()
oauth = OAuth()
"""
cors = CORS(app, resources={
r"/static/*": {
"origins": [app.config["URL_HOST"]],
"methods": ["GET"],
"max_age": 3600
}
})
csrf.init_app(app)
cors.init_app(app)
@@ -113,9 +107,9 @@ with app.app_context():
)
app.register_blueprint(routes_core)
app.register_blueprint(routes_core_home)
app.register_blueprint(routes_core_contact)
app.register_blueprint(routes_legal)
app.register_blueprint(routes_user)
@@ -123,3 +117,13 @@ app.register_blueprint(routes_user)
def console_log(value):
Helper_App.console_log(value)
return value
@app.after_request
def add_cache_headers(response):
if request.path.startswith('/static/'):
# Cache static assets
response.headers['Cache-Control'] = 'public, max-age=31536000'
else:
# No caching for dynamic content
response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
return response

View File

@@ -1,107 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Address Business Object
Description:
Business object for address
"""
# internal
import lib.argument_validation as av
from business_objects.base import Base
from business_objects.region import Region
from extensions import db
from helpers.helper_app import Helper_App
# external
from typing import ClassVar
from flask import jsonify
class Address(db.Model, Base):
FLAG_ADDRESS_LINE_1: ClassVar[str] = 'address_line_1'
FLAG_ADDRESS_LINE_2: ClassVar[str] = 'address_line_2'
FLAG_CITY: ClassVar[str] = 'city'
FLAG_COUNTY: ClassVar[str] = 'county'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_ADDRESS
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_POSTCODE
__tablename__ = 'Shop_Address'
id_address = db.Column(db.Integer, primary_key=True)
id_region = db.Column(db.Integer)
postcode = db.Column(db.String(20))
address_line_1 = db.Column(db.String(256))
address_line_2 = db.Column(db.String(256))
city = db.Column(db.String(256))
county = db.Column(db.String(256))
active = db.Column(db.Boolean)
# region = None
def __init__(self):
super().__init__()
Base.__init__(self)
self.region = None
@classmethod
def from_DB_storage_location(cls, query_row):
address = cls()
address.id_address = query_row[2]
address.id_region = query_row[3]
return address
@classmethod
def from_DB_plant(cls, query_row):
address = cls()
address.id_address = query_row[1]
address.id_region = query_row[2]
return address
@classmethod
def from_DB_stock_item(cls, query_row):
address = cls()
address.id_address = query_row[6]
address.id_region = query_row[7]
return address
@classmethod
def from_DB_supplier(cls, query_row):
address = cls()
address.id_address = query_row[1]
address.postcode = query_row[2]
return address
def __repr__(self):
return f'''
{self.ATTR_ID_ADDRESS}: {self.id_address}
{self.FLAG_REGION}: {self.region}
{self.FLAG_POSTCODE}: {self.postcode}
{self.FLAG_ADDRESS_LINE_1}: {self.address_line_1}
{self.FLAG_ADDRESS_LINE_2}: {self.address_line_2}
{self.FLAG_CITY}: {self.city}
{self.FLAG_COUNTY}: {self.county}
{self.FLAG_ACTIVE}: {self.active}
'''
def to_json(self):
return {
**self.get_shared_json_attributes(self),
self.ATTR_ID_ADDRESS: self.id_address,
self.FLAG_REGION: None if self.region is None else self.region.to_json(),
self.FLAG_POSTCODE: self.postcode,
self.FLAG_ADDRESS_LINE_1: self.address_line_1,
self.FLAG_ADDRESS_LINE_2: self.address_line_2,
self.FLAG_CITY: self.city,
self.FLAG_COUNTY: self.county,
self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0
}
def to_json_str(self):
return jsonify(self.to_json())
@classmethod
def from_json(cls, json):
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
address = cls()
address.id_address = json[cls.ATTR_ID_ADDRESS],
address.region = Region.from_json(json[cls.FLAG_REGION]),
address.postcode = json[cls.FLAG_POSTCODE],
address.address_line_1 = json[cls.FLAG_ADDRESS_LINE_1],
address.address_line_2 = json.get(cls.FLAG_ADDRESS_LINE_2, ''),
address.city = json[cls.FLAG_CITY],
address.county = json[cls.FLAG_COUNTY],
address.active = json[cls.FLAG_ACTIVE]
return address

32
business_objects/api.py Normal file
View File

@@ -0,0 +1,32 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Base Business Object
Description:
Abstract business object
"""
# internal
from extensions import db
import lib.argument_validation as av
# external
from typing import ClassVar
from flask import jsonify
class API():
@staticmethod
def get_standard_response(success: bool, status_code: int, message: str, data: any, errors: list, meta: dict):
return jsonify({
"success": success,
"status_code": status_code,
"message": message,
"data": data,
"errors": errors,
"meta": meta
})

View File

@@ -7,7 +7,7 @@ Technology: Business Objects
Feature: Base Business Object
Description:
Abstract business object
Abstract base class for all business objects in app
"""
# internal
@@ -67,6 +67,7 @@ class Base():
FLAG_VALUE_LOCAL_VAT_EXCL: ClassVar[str] = 'value_local_vat_excl'
FLAG_VALUE_LOCAL_VAT_INCL: ClassVar[str] = 'value_local_vat_incl'
FLAG_WEBSITE: ClassVar[str] = 'website'
ID_USER_GUEST: ClassVar[int] = 3
"""
NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'name-attribute-option-text'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = 'name-attribute-option-value'

View File

@@ -1,147 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Product Business Object
Description:
Business object for product
"""
# internal
from business_objects.store.store_base import Store_Base
from extensions import db
from lib import argument_validation as av
# external
from typing import ClassVar
# CLASSES
"""
class Currency_Enum(Enum):
GBP = 1
def text(self):
return Currency_Enum.Currency_Enum_Text(self)
def Currency_Enum_Text(currency):
av.val_instance(currency, 'currency', 'Currency_Enum_Text', Currency_Enum)
if currency == Currency_Enum.GBP:
return 'GBP'
else:
# return 'Unknown'
raise ValueError("Unknown Currency Enum.")
def get_member_by_text(text):
for member in Resolution_Level_Enum.__members__.values():
if member.name == text:
return member
raise ValueError("Unknown Currency Enum.")
# return Resolution_Level_Enum.HIGH
"""
class Currency(db.Model, Store_Base):
FLAG_FACTOR_FROM_GBP: ClassVar[str] = 'factor-from-GBP'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_CURRENCY
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
id_currency = db.Column(db.Integer, primary_key=True)
code = db.Column(db.String(50))
name = db.Column(db.String(255))
symbol = db.Column(db.String(50))
factor_from_GBP = db.Column(db.Float)
display_order = db.Column(db.Integer)
active = db.Column(db.Boolean)
@classmethod
def from_DB_currency(cls, query_row):
_m = 'Currency.from_DB_currency'
v_arg_type = 'class attribute'
currency = cls()
currency.id_currency = query_row[0]
currency.code = query_row[1]
currency.name = query_row[2]
currency.symbol = query_row[3]
currency.factor_from_GBP = query_row[4]
currency.display_order = query_row[5]
currency.active = av.input_bool(query_row[6], 'active', _m, v_arg_type=v_arg_type)
return currency
@classmethod
def from_DB_get_many_product_catalogue_product_permutation(cls, query_row):
currency = cls()
currency.id_currency = query_row[6]
currency.code = query_row[7]
currency.symbol = query_row[8]
return currency
@classmethod
def from_DB_get_many_product_price_and_discount_and_delivery_region(cls, query_row):
currency = cls()
return currency
@classmethod
def from_DB_stock_item(cls, query_row):
currency = cls()
currency.id_currency = query_row[12]
currency.code = query_row[13]
currency.symbol = query_row[14]
return currency
@classmethod
def from_DB_supplier(cls, query_row):
currency = cls()
currency.id_currency = query_row[1]
currency.code = query_row[2]
currency.symbol = query_row[3]
return currency
@classmethod
def from_DB_supplier_purchase_order(cls, query_row):
currency = cls()
currency.id_currency = query_row[3]
currency.code = query_row[4]
currency.symbol = query_row[5]
return currency
@classmethod
def from_DB_manufacturing_purchase_order(cls, query_row):
currency = cls()
currency.id_currency = query_row[1]
currency.code = query_row[2]
currency.symbol = query_row[3]
return currency
def __repr__(self):
return f'''
id: {self.id_currency}
name: {self.name}
code: {self.code}
symbol: {self.symbol}
factor from GBP: {self.factor_from_GBP}
display_order: {self.display_order}
active: {self.active}
'''
def to_json(self):
return {
**self.get_shared_json_attributes(self),
self.NAME_ATTR_OPTION_TEXT: self.FLAG_NAME,
self.NAME_ATTR_OPTION_VALUE: self.ATTR_ID_CURRENCY,
self.ATTR_ID_CURRENCY: self.id_currency,
self.FLAG_CODE: self.code,
self.FLAG_NAME: self.name,
self.FLAG_SYMBOL: self.symbol,
self.FLAG_FACTOR_FROM_GBP: self.factor_from_GBP,
self.FLAG_DISPLAY_ORDER: self.display_order,
self.FLAG_ACTIVE: self.active,
}
@classmethod
def from_json(cls, json_currency, key_suffix = ''):
currency = cls()
currency.id_currency = json_currency[f'{cls.ATTR_ID_CURRENCY}{key_suffix}']
currency.code = json_currency.get(f'{cls.FLAG_CODE}{key_suffix}')
currency.name = json_currency.get(f'{cls.FLAG_NAME}{key_suffix}')
currency.symbol = json_currency.get(f'{cls.FLAG_SYMBOL}{key_suffix}')
currency.factor_from_GBP = json_currency.get(f'{cls.FLAG_FACTOR_FROM_GBP}{key_suffix}')
currency.display_order = json_currency.get(f'{cls.FLAG_DISPLAY_ORDER}{key_suffix}')
currency.active = json_currency.get(f'{cls.FLAG_ACTIVE}{key_suffix}')
return currency
def to_json_option(self):
return {
'value': self.id_currency,
'text': self.name
}

View File

@@ -7,7 +7,7 @@ Technology: Business Objects
Feature: Database Base Business Objects
Description:
Abstract business object for database objects
Abstract base class for database objects
"""
# internal
@@ -22,32 +22,7 @@ from sqlalchemy.ext.declarative import DeclarativeMeta
# from flask_sqlalchemy import SQLAlchemy
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
def to_json(self):
return self.dict()
"""
@classmethod
@abstractmethod
def from_json(cls, json):
pass
"""
"""
@classmethod
@abstractmethod
def from_form(cls, form):
pass
"""
# db = SQLAlchemy()
# Base = declarative_base()
class SQLAlchemy_ABCMeta(db.Model.__class__, ABCMeta):
pass
@@ -63,10 +38,6 @@ class SQLAlchemy_ABC(db.Model, metaclass=SQLAlchemy_ABCMeta):
@classmethod
def from_json(cls, json):
pass
"""
def to_json_option(self):
pass
"""
def to_temporary_record(self):
pass
def to_object_with_missing_attributes(self, excluded_attributes):

View File

@@ -23,16 +23,13 @@ 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__ = 'Shop_Access_Level_Temp'
__tablename__ = 'PH_Access_Level_Temp'
id_access_level = db.Column(db.Integer, primary_key=True)
code = db.Column(db.String(50))
name = db.Column(db.String(255))
description = db.Column(db.String(4000))
priority = db.Column(db.Integer)
display_order = db.Column(db.Integer)
active = db.Column(db.Boolean)
created_on = db.Column(db.DateTime)
created_by = db.Column(db.Integer)
def __init__(self):
super().__init__()
Base.__init__(self)
@@ -74,7 +71,6 @@ class Access_Level(db.Model, Base):
}
@classmethod
def from_json(cls, json):
Helper_App.console_log(f'Access Level.from_json: {json}')
access_level = cls()
access_level.id_access_level = json[cls.ATTR_ID_ACCESS_LEVEL],
access_level.code = json[cls.FLAG_CODE],

View File

View File

@@ -0,0 +1,136 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Contact_Form 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
# external
from dataclasses import dataclass
from typing import ClassVar
class Contact_Form(SQLAlchemy_ABC, Base):
FLAG_ALTCHA: ClassVar[str] = 'altcha'
FLAG_CONTACT_FORM: ClassVar[str] = 'contact-form'
FLAG_NAME_COMPANY: ClassVar[str] = 'name-company'
FLAG_NAME_CONTACT: ClassVar[str] = 'name-contact'
FLAG_MESSAGE: ClassVar[str] = 'message'
FLAG_RECEIVE_MARKETING_COMMUNICATIONS: ClassVar[str] = 'receive-marketing-communications'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = FLAG_CONTACT_FORM
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_EMAIL
__tablename__ = 'PH_Contact_Form'
__table_args__ = { 'extend_existing': True }
id_contact_form = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255))
name_contact = db.Column(db.String(255))
name_company = db.Column(db.String(255))
message = db.Column(db.Text)
receive_marketing_communications = db.Column(db.Boolean)
active = db.Column(db.Boolean)
created_on = db.Column(db.DateTime)
def __init__(self):
self.id_contact_form = 0
self.is_new = False
super().__init__()
def from_DB_Contact_Form(query_row):
_m = 'Contact_Form.from_DB_Contact_Form'
contact_form = Contact_Form()
contact_form.id_contact_form = query_row[0]
contact_form.email = query_row[1]
contact_form.name_contact = query_row[2]
contact_form.name_company = query_row[3]
contact_form.message = query_row[4]
contact_form.receive_marketing_communications = av.input_bool(query_row[5], 'receive_marketing_communications', _m)
contact_form.active = av.input_bool(query_row[6], 'active', _m)
contact_form.created_on = query_row[7]
return contact_form
@classmethod
def from_json(cls, json):
_m = 'Contact_Form.from_json'
contact_form = cls()
if json is None: return Contact_Form
Helper_App.console_log(f'{_m}\njson: {json}')
contact_form.id_contact_form = -1
contact_form.email = json[cls.FLAG_EMAIL]
contact_form.name_contact = json[cls.FLAG_NAME_CONTACT]
contact_form.name_company = json[cls.FLAG_NAME_COMPANY]
contact_form.message = json[cls.FLAG_MESSAGE]
contact_form.receive_marketing_communications = json[cls.FLAG_RECEIVE_MARKETING_COMMUNICATIONS]
contact_form.active = json[cls.FLAG_ACTIVE]
contact_form.created_on = json.get(cls.FLAG_CREATED_ON, None)
Helper_App.console_log(f'Contact_Form: {contact_form}')
return contact_form
def to_json(self):
as_json = {
self.FLAG_CONTACT_FORM: self.id_contact_form
, self.FLAG_EMAIL: self.email
, self.FLAG_NAME_CONTACT: self.name_contact
, self.FLAG_NAME_COMPANY: self.name_company
, self.FLAG_MESSAGE: self.message
, self.FLAG_RECEIVE_MARKETING_COMMUNICATIONS: self.receive_marketing_communications
, self.FLAG_ACTIVE: self.active
, self.FLAG_CREATED_ON: self.created_on
}
Helper_App.console_log(f'as_json: {as_json}')
return as_json
def __repr__(self):
return f'''
{self.__class__.__name__}(
{self.FLAG_CONTACT_FORM}: {self.id_contact_form}
{self.FLAG_EMAIL}: {self.email}
{self.FLAG_NAME_CONTACT}: {self.name_contact}
{self.FLAG_NAME_COMPANY}: {self.name_company}
{self.FLAG_MESSAGE}: {self.message}
{self.FLAG_RECEIVE_MARKETING_COMMUNICATIONS}: {self.receive_marketing_communications}
{self.FLAG_ACTIVE}: {self.active}
{self.FLAG_CREATED_ON}: {self.created_on}
)
'''
class Contact_Form_Temp(db.Model, Base):
__tablename__ = 'PH_Contact_Form_Temp'
__table_args__ = { 'extend_existing': True }
id_temp = db.Column(db.Integer, primary_key=True)
id_contact_form = db.Column(db.Integer)
email = db.Column(db.String(255))
name_contact = db.Column(db.String(255))
name_company = db.Column(db.String(255))
message = db.Column(db.Text)
receive_marketing_communications = db.Column(db.Boolean)
active = db.Column(db.Boolean)
created_on = db.Column(db.DateTime)
guid: str = db.Column(db.String(36))
def __init__(self):
super().__init__()
@classmethod
def from_contact_form(cls, contact_form):
_m = 'Contact_Form_Temp.from_Contact_Form'
temp = cls()
temp.id_contact_form = contact_form.id_contact_form
temp.email = contact_form.email
temp.name_contact = contact_form.name_contact
temp.name_company = contact_form.name_company
temp.message = contact_form.message
temp.receive_marketing_communications = contact_form.receive_marketing_communications
temp.active = contact_form.active
temp.created_on = contact_form.created_on
return temp

View File

@@ -0,0 +1,133 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
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
# external
from dataclasses import dataclass
from typing import ClassVar
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'
__table_args__ = { 'extend_existing': True }
id_user = db.Column(db.Integer, primary_key=True)
id_user_auth0 = db.Column(db.String(255))
firstname = db.Column(db.String(255))
surname = db.Column(db.String(255))
email = db.Column(db.String(255))
is_email_verified = db.Column(db.Boolean)
is_super_user = db.Column(db.Boolean)
is_new = db.Column(db.Boolean)
def __init__(self):
self.id_user = 0
self.is_new = False
super().__init__()
def from_DB_user(query_row):
_m = 'User.from_DB_user'
user = User()
user.id_user = query_row[0]
user.id_user_auth0 = query_row[1]
user.firstname = query_row[2]
user.surname = query_row[3]
user.email = query_row[4]
user.is_email_verified = av.input_bool(query_row[5], 'is_email_verified', _m)
user.is_super_user = av.input_bool(query_row[9], 'is_super_user', _m)
user.is_new = av.input_bool(query_row[12], 'is_new', _m)
return user
@staticmethod
def from_json(json):
_m = 'User.from_json'
user = User()
if json is None: return user
Helper_App.console_log(f'{_m}\njson: {json}')
user.id_user = json['id_user']
user.id_user_auth0 = json['id_user_auth0']
user.firstname = json['firstname']
user.surname = json['surname']
user.email = json['email']
user.is_email_verified = av.input_bool(json['is_email_verified'], 'is_email_verified', _m)
user.is_super_user = av.input_bool(json['is_super_user'], 'is_super_user', _m)
Helper_App.console_log(f'user: {user}')
return user
@staticmethod
def from_json_auth0(json):
_m = 'User.from_json_auth0'
user = User()
if json is None: return user
Helper_App.console_log(f'{_m}\njson: {json}')
user_info = json['userinfo']
user.id_user = None
user.id_user_auth0 = user_info['sub']
user.firstname = None
user.surname = None
user.email = user_info['email']
user.is_email_verified = av.input_bool(user_info['email_verified'], 'is_email_verified', _m)
user.is_super_user = None
Helper_App.console_log(f'user: {user}')
return user
def to_json(self):
as_json = {
'id_user': self.id_user,
'id_user_auth0': self.id_user_auth0,
'firstname': self.firstname,
'surname': self.surname,
'email': self.email,
'is_email_verified': self.is_email_verified,
'is_super_user': self.is_super_user
}
Helper_App.console_log(f'as_json: {as_json}')
return as_json
def __repr__(self):
return f'''
id_user: {self.id_user}
id_user_auth0: {self.id_user_auth0}
firstname: {self.firstname}
surname: {self.surname}
email: {self.email}
is_email_verified: {self.is_email_verified}
is_super_user: {self.is_super_user}
'''
def get_is_logged_in(self):
return (self.id_user > 0 and self.id_user != Base.ID_USER_GUEST)
class User_Temp(db.Model, Base):
__tablename__ = 'Shop_User_Temp'
__table_args__ = { 'extend_existing': True }
id_user = db.Column(db.Integer, primary_key=True)
id_user_auth0 = db.Column(db.String(255))
firstname = db.Column(db.String(255))
surname = db.Column(db.String(255))
email = db.Column(db.String(255))
is_email_verified = db.Column(db.Boolean)
is_super_user = db.Column(db.Boolean)
id_currency_default = db.Column(db.Integer)
id_region_default = db.Column(db.Integer)
is_included_VAT_default = db.Column(db.Boolean)
# is_logged_in: bool
def __init__(self):
self.id_user = 0
super().__init__()

View File

@@ -1,87 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Address Region Business Object
Description:
Business object for address region
"""
# internal
import lib.argument_validation as av
from business_objects.base import Base
from extensions import db
from helpers.helper_app import Helper_App
# external
from typing import ClassVar
class Region(db.Model, Base):
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_REGION
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME
__tablename__ = 'Shop_Region'
id_region = db.Column(db.Integer, primary_key=True)
code = db.Column(db.String(50))
name = db.Column(db.String(200))
active = db.Column(db.Boolean)
# region = None
def __init__(self):
super().__init__()
Base.__init__(self)
@classmethod
def from_DB_stock_item(cls, query_row):
region = cls()
region.id_region = query_row[7]
return region
@classmethod
def from_DB_supplier(cls, query_row):
region = cls()
region.id_region = query_row[2]
region.name = query_row[3]
return region
def __repr__(self):
return f'''
{self.ATTR_ID_REGION}: {self.id_region}
{self.FLAG_CODE}: {self.code}
{self.FLAG_NAME}: {self.name}
{self.FLAG_ACTIVE}: {self.active}
'''
def to_json(self):
return {
**self.get_shared_json_attributes(self),
self.ATTR_ID_REGION: self.id_region,
self.FLAG_CODE: self.code,
self.FLAG_NAME: self.name,
self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0
}
@classmethod
def from_json(cls, json):
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
plant = cls()
plant.id_region = json[cls.ATTR_ID_REGION]
plant.code = json[cls.FLAG_CODE]
plant.name = json[cls.FLAG_NAME]
plant.active = json[cls.FLAG_ACTIVE]
return plant
@classmethod
def from_DB_get_many_product_catalogue(cls, query_row):
region = cls()
region.id_region = query_row[0]
region.name = query_row[1]
region.code = query_row[2]
# self.display_order = query_row[3]
return region
@classmethod
def from_DB_region(cls, query_row):
region = cls()
region.id_region = query_row[0]
region.code = query_row[1]
region.name = query_row[2]
region.active = av.input_bool(query_row[3], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_region')
return region

View File

@@ -7,7 +7,7 @@ Technology: Business Objects
Feature: SQL Error Business Object
Description:
Business object for SQL errors
Business object for SQL errors returned by Get Many Stored Procedures
"""
# internal
@@ -22,11 +22,9 @@ import locale
from flask_sqlalchemy import SQLAlchemy
# VARIABLE INSTANTIATION
db = SQLAlchemy()
# CLASSES
class SQL_Error(db.Model):
display_order = db.Column(db.Integer, primary_key=True)
id_type = db.Column(db.Integer)

View File

@@ -1,110 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Unit of Measurement Business Object
"""
# internal
from business_objects.base import Base
from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
from extensions import db
# from forms.forms import Form_Filters_User
from helpers.helper_app import Helper_App
import lib.argument_validation as av
# external
from dataclasses import dataclass
from typing import ClassVar
class Unit_Measurement(SQLAlchemy_ABC, Base):
ATTR_ID_UNIT_MEASUREMENT: ClassVar[str] = 'id_unit_measurement'
FLAG_IS_BASE_UNIT: ClassVar[str] = 'is_base_unit'
FLAG_IS_UNIT_OF_DISTANCE: ClassVar[str] = 'is_unit_of_distance'
FLAG_IS_UNIT_OF_MASS: ClassVar[str] = 'is_unit_of_mass'
FLAG_IS_UNIT_OF_TIME: ClassVar[str] = 'is_unit_of_time'
FLAG_IS_UNIT_OF_VOLUME: ClassVar[str] = 'is_unit_of_volume'
FLAG_NAME_PLURAL: ClassVar[str] = 'name_plural'
FLAG_NAME_SINGULAR: ClassVar[str] = 'name_singular'
FLAG_SYMBOL: ClassVar[str] = 'symbol'
FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX: ClassVar[str] = 'symbol_is_suffix_not_prefix'
# KEY_UNIT_MEASUREMENT: ClassVar[str] = 'unit_of_measurement'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_ID_UNIT_MEASUREMENT
NAME_ATTR_OPTION_TEXT: ClassVar[str] = FLAG_NAME_SINGULAR
id_unit_measurement = db.Column(db.Integer, primary_key=True)
name_singular = db.Column(db.String(255))
name_plural = db.Column(db.String(256))
symbol = db.Column(db.String(50))
symbol_is_suffix_not_prefix = db.Column(db.Boolean)
is_base_unit = db.Column(db.Boolean)
is_unit_of_distance = db.Column(db.Boolean)
is_unit_of_mass = db.Column(db.Boolean)
is_unit_of_time = db.Column(db.Boolean)
is_unit_of_volume = db.Column(db.Boolean)
active = db.Column(db.Boolean)
def from_DB_unit_measurement(query_row):
_m = 'Unit_Measurement.from_DB_unit_measurement'
unit = Unit_Measurement()
unit.id_unit_measurement = query_row[0]
unit.name_singular = query_row[1]
unit.name_plural = query_row[2]
unit.symbol = query_row[3]
unit.symbol_is_suffix_not_prefix = av.input_bool(query_row[4], 'symbol_is_suffix_not_prefix', _m)
unit.is_base_unit = av.input_bool(query_row[5], 'is_base_unit', _m)
unit.is_unit_of_distance = av.input_bool(query_row[6], 'is_unit_of_distance', _m)
unit.is_unit_of_mass = av.input_bool(query_row[7], 'is_unit_of_mass', _m)
unit.is_unit_of_time = av.input_bool(query_row[8], 'is_unit_of_time', _m)
unit.is_unit_of_volume = av.input_bool(query_row[9], 'is_unit_of_volume', _m)
unit.active = av.input_bool(query_row[10], 'active', _m)
return unit
def to_json(self):
return {
**self.get_shared_json_attributes(self),
self.ATTR_ID_UNIT_MEASUREMENT: self.id_unit_measurement,
self.FLAG_NAME_SINGULAR: self.name_singular,
self.FLAG_NAME_PLURAL: self.name_plural,
self.FLAG_SYMBOL: self.symbol,
self.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX: self.symbol_is_suffix_not_prefix,
self.FLAG_IS_BASE_UNIT: self.is_base_unit,
self.FLAG_IS_UNIT_OF_DISTANCE: self.is_unit_of_distance,
self.FLAG_IS_UNIT_OF_MASS: self.is_unit_of_mass,
self.FLAG_IS_UNIT_OF_TIME: self.is_unit_of_time,
self.FLAG_IS_UNIT_OF_VOLUME: self.is_unit_of_volume,
self.FLAG_ACTIVE: self.active,
}
@classmethod
def from_json(cls, json):
Helper_App.console_log(f' Unit_Measurement.from_json: {json}')
unit = cls()
unit.id_unit_measurement = json[cls.ATTR_ID_UNIT_MEASUREMENT]
unit.name_singular = json[cls.FLAG_NAME_SINGULAR]
unit.name_plural = json[cls.FLAG_NAME_PLURAL]
unit.symbol = json[cls.FLAG_SYMBOL]
unit.symbol_is_suffix_not_prefix = json[cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX]
unit.is_base_unit = json[cls.FLAG_IS_BASE_UNIT]
unit.is_unit_of_distance = json[cls.FLAG_IS_UNIT_OF_DISTANCE]
unit.is_unit_of_mass = json[cls.FLAG_IS_UNIT_OF_MASS]
unit.is_unit_of_time = json[cls.FLAG_IS_UNIT_OF_TIME]
unit.is_unit_of_volume = json[cls.FLAG_IS_UNIT_OF_VOLUME]
unit.active = json[cls.FLAG_ACTIVE]
return unit
def __repr__(self):
return f'''
id_unit_of_measurement: {self.id_unit_measurement},
name_singular: {self.name_singular},
name_plural: {self.name_plural},
symbol: {self.symbol},
symbol_is_suffix_not_prefix: {self.symbol_is_suffix_not_prefix},
is_base_unit: {self.is_base_unit},
is_unit_of_distance: {self.is_unit_of_distance},
is_unit_of_mass: {self.is_unit_of_mass},
is_unit_of_time: {self.is_unit_of_time},
is_unit_of_volume: {self.is_unit_of_volume},
active: {self.active}
'''

View File

@@ -1,293 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: User Business Object
"""
# internal
from business_objects.base import Base
from business_objects.db_base import Get_Many_Parameters_Base
import lib.argument_validation as av
from forms.forms import Form_Filters_User
from extensions import db
from helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar
class User(db.Model, Base):
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_USER
NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'email'
__tablename__ = 'Shop_User'
__table_args__ = { 'extend_existing': True }
id_user = db.Column(db.Integer, primary_key=True)
id_user_auth0 = db.Column(db.String(255))
firstname = db.Column(db.String(255))
surname = db.Column(db.String(255))
email = db.Column(db.String(255))
is_email_verified = db.Column(db.Boolean)
is_super_user = db.Column(db.Boolean)
id_currency_default = db.Column(db.Integer)
id_region_default = db.Column(db.Integer)
is_included_VAT_default = db.Column(db.Boolean)
can_admin_store = db.Column(db.Boolean)
can_admin_user = db.Column(db.Boolean)
is_new = db.Column(db.Boolean)
# is_logged_in: bool
def __init__(self):
self.id_user = 0
self.is_logged_in = False
self.is_new = False
super().__init__()
self.currency_default = None
self.region_default = None
def from_DB_user(query_row):
_m = 'User.from_DB_user'
user = User()
user.id_user = query_row[0]
user.id_user_auth0 = query_row[1]
user.firstname = query_row[2]
user.surname = query_row[3]
user.email = query_row[4]
user.is_email_verified = av.input_bool(query_row[5], 'is_email_verified', _m)
user.id_currency_default = query_row[6]
user.id_region_default = query_row[7]
user.is_included_VAT_default = av.input_bool(query_row[8], 'is_included_VAT_default', _m)
user.is_super_user = av.input_bool(query_row[9], 'is_super_user', _m)
user.can_admin_store = av.input_bool(query_row[10], 'can_admin_store', _m)
user.can_admin_user = av.input_bool(query_row[11], 'can_admin_user', _m)
user.is_logged_in = (user.id_user is not None and user.id_user > 0)
user.is_new = av.input_bool(query_row[12], 'is_new', _m)
return user
@staticmethod
def from_json(json):
_m = 'User.from_json'
user = User()
if json is None: return user
Helper_App.console_log(f'{_m}\njson: {json}')
user.id_user = json['id_user']
user.id_user_auth0 = json['id_user_auth0']
user.firstname = json['firstname']
user.surname = json['surname']
user.email = json['email']
user.is_email_verified = av.input_bool(json['is_email_verified'], 'is_email_verified', _m)
user.is_super_user = av.input_bool(json['is_super_user'], 'is_super_user', _m)
user.id_currency_default = json['id_currency_default']
user.id_region_default = json['id_region_default']
user.is_included_VAT_default = av.input_bool(json['is_included_VAT_default'], 'is_included_VAT_default', _m)
user.can_admin_store = av.input_bool(json['can_admin_store'], 'can_admin_store', _m)
user.can_admin_user = av.input_bool(json['can_admin_user'], 'can_admin_user', _m)
user.is_logged_in = (user.id_user_auth0 is not None)
Helper_App.console_log(f'user: {user}')
return user
# Helper_App.console_log(f'user: {user}')
@staticmethod
def from_json_auth0(json):
_m = 'User.from_json_auth0'
user = User()
if json is None: return user
Helper_App.console_log(f'{_m}\njson: {json}')
user_info = json['userinfo']
user.id_user = None
user.id_user_auth0 = user_info['sub']
user.firstname = None
user.surname = None
user.email = user_info['email']
user.is_email_verified = av.input_bool(user_info['email_verified'], 'is_email_verified', _m)
user.is_super_user = None
user.id_currency_default = None
user.id_region_default = None
user.is_included_VAT_default = None
user.can_admin_store = None
user.can_admin_user = None
user.is_logged_in = (user.id_user_auth0 is not None and user.id_user_auth0 != '')
Helper_App.console_log(f'user: {user}')
return user
def to_json(self):
as_json = {
'id_user': self.id_user,
'id_user_auth0': self.id_user_auth0,
'firstname': self.firstname,
'surname': self.surname,
'email': self.email,
'is_email_verified': self.is_email_verified,
'is_super_user': self.is_super_user,
'id_currency_default': self.id_currency_default,
'id_region_default': self.id_region_default,
'is_included_VAT_default': self.is_included_VAT_default,
'can_admin_store': self.can_admin_store,
'can_admin_user': self.can_admin_user
}
Helper_App.console_log(f'as_json: {as_json}')
return as_json
def __repr__(self):
return f'''
id_user: {self.id_user}
id_user_auth0: {self.id_user_auth0}
firstname: {self.firstname}
surname: {self.surname}
email: {self.email}
is_email_verified: {self.is_email_verified}
is_super_user: {self.is_super_user}
id_currency_default: {self.id_currency_default}
id_region_default: {self.id_region_default}
is_included_VAT_default: {self.is_included_VAT_default}
can_admin_store: {self.can_admin_store}
can_admin_user: {self.can_admin_user}
'''
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 = ''
)
""" User_Eval
@dataclass
class User_Filters():
ids_user: str
get_inactive_users: bool
ids_permission: str
ids_access_level: str
ids_product: str
def to_json(self):
return {
**self.get_shared_json_attributes(self),
'a_ids_user': self.ids_user,
'a_get_inactive_users': self.get_inactive_users,
'a_ids_permission': self.ids_permission,
'a_ids_access_level': self.ids_access_level,
'a_ids_product': self.ids_product,
}
@staticmethod
def from_form(form):
av.val_instance(form, 'form', 'User_Filters.from_form', Form_Filters_User)
get_inactive = av.input_bool(form.active.data, "active", "User_Filters.from_form")
return User_Filters(
ids_user = form.id_user.data,
get_inactive_users = get_inactive,
ids_permission = form.ids_permission.data,
ids_access_level = form.ids_access_level.data,
ids_product = form.ids_product.data,
)
@staticmethod
def get_default(datastore_store):
is_user_logged_in, id_user = datastore_store.get_login_user()
return User_Filters(
ids_user = id_user,
get_inactive_users = False,
ids_permission = '',
ids_access_level = '',
ids_product = '',
)
"""
class User_Permission_Evaluation(db.Model):
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}
'''
class User_Temp(db.Model, Base):
__tablename__ = 'Shop_User_Temp'
__table_args__ = { 'extend_existing': True }
id_user = db.Column(db.Integer, primary_key=True)
id_user_auth0 = db.Column(db.String(255))
firstname = db.Column(db.String(255))
surname = db.Column(db.String(255))
email = db.Column(db.String(255))
is_email_verified = db.Column(db.Boolean)
is_super_user = db.Column(db.Boolean)
id_currency_default = db.Column(db.Integer)
id_region_default = db.Column(db.Integer)
is_included_VAT_default = db.Column(db.Boolean)
# is_logged_in: bool
def __init__(self):
self.id_user = 0
self.is_logged_in = False
super().__init__()

View File

@@ -11,7 +11,6 @@ Configuration variables
"""
# IMPORTS
from lib import argument_validation as av
import os
from dotenv import load_dotenv, find_dotenv
from flask import current_app
@@ -40,8 +39,8 @@ class Config:
# Auth0
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
# SESSION_COOKIE_SAMESITE = 'Lax'
# PERMANENT_SESSION_LIFETIME = 3600
SESSION_COOKIE_SAMESITE = 'Strict'
REMEMBER_COOKIE_SECURE = True
WTF_CSRF_ENABLED = True
# WTF_CSRF_CHECK_DEFAULT = False # We'll check it manually for API routes
# WTF_CSRF_HEADERS = ['X-CSRFToken'] # Accept CSRF token from this header
@@ -52,7 +51,7 @@ class Config:
DOMAIN_AUTH0 = os.getenv('DOMAIN_AUTH0')
ID_TOKEN_USER = 'user'
# PostgreSQL
DB_NAME = os.getenv('partsltd')
DB_NAME = os.getenv('partsltd_prod')
DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_HOST = os.getenv('DB_HOST')
@@ -80,9 +79,15 @@ class Config:
MAIL_PASSWORD = os.getenv('MAIL_PASSWORD')
MAIL_DEFAULT_SENDER = os.getenv('MAIL_DEFAULT_SENDER')
MAIL_CONTACT_PUBLIC = os.getenv('MAIL_CONTACT_PUBLIC')
"""
# Recaptcha
RECAPTCHA_PUBLIC_KEY = os.getenv('RECAPTCHA_PUBLIC_KEY')
RECAPTCHA_PRIVATE_KEY = os.getenv('RECAPTCHA_PRIVATE_KEY')
"""
# ALTCHA
ALTCHA_API_KEY = os.getenv('ALTCHA_API_KEY')
ALTCHA_SECRET_KEY = os.getenv('ALTCHA_SECRET_KEY')
ALTCHA_REGION = 'eu'
class DevelopmentConfig(Config):
is_development = True

View File

@@ -1,73 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Core Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# IMPORTS
# internal
from datastores.datastore_base import DataStore_Base
from forms.contact import Form_Contact
from models.model_view_contact import Model_View_Contact
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
from flask_mail import Mail, Message
from extensions import db, oauth, mail
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
routes_core = Blueprint('routes_core', __name__)
@routes_core.route(Model_View_Home.HASH_PAGE_HOME, methods=['GET'])
def home():
try:
model = Model_View_Home()
html_body = render_template('pages/core/_home.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
@routes_core.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['GET'])
def contact():
try:
form = Form_Contact()
model = Model_View_Contact(form)
html_body = render_template('pages/core/_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body
@routes_core.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['POST'])
def contact_post():
try:
form = Form_Contact()
if form.validate_on_submit():
# Handle form submission
email = form.email.data
CC = form.CC.data # not in use
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." 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)
return "Submitted."
return "Invalid. Failed to submit."
# html_body = render_template('pages/core/_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403

View File

143
controllers/core/contact.py Normal file
View File

@@ -0,0 +1,143 @@
"""
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.contact_form import Contact_Form
from datastores.project_hub.datastore_contact_form import DataStore_Contact_Form
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_Contact_Form()
contact_form = Contact_Form.from_json(form.to_json())
datastore.save_contact_forms(
comment = contact_form.message
, contact_forms = [contact_form]
)
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
)

31
controllers/core/home.py Normal file
View File

@@ -0,0 +1,31 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: Core - Home Routes
Description:
Home Page Controller.
"""
# internal
from business_objects.api import API
from models.model_view_home import Model_View_Home
# external
from flask import render_template, jsonify, Blueprint
routes_core_home = Blueprint('routes_core_home', __name__)
@routes_core_home.route(Model_View_Home.HASH_PAGE_HOME, methods=['GET'])
def home():
try:
model = Model_View_Home()
html_body = render_template('pages/core/_home.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
return html_body

View File

View File

@@ -7,7 +7,7 @@ Technology: App Routing
Feature: Legal Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
Legal Section Controller.
"""
# IMPORTS
@@ -20,12 +20,8 @@ from models.model_view_accessibility_statement import Model_View_Accessibility_S
from models.model_view_retention_schedule import Model_View_Retention_Schedule
import lib.argument_validation as av
# external
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
from flask import render_template, Blueprint
routes_legal = Blueprint('routes_legal', __name__)

View File

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

View File

@@ -1,243 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App Routing
Feature: User Routes
Description:
Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles.
"""
# IMPORTS
# internal
from models.model_view_base import Model_View_Base
from models.model_view_user import Model_View_User
from business_objects.user import User, 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'])
def login():
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')
red = oauth.auth0.authorize_redirect(
redirect_uri = uri_redirect,
state = quote(hash_callback)
)
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") # <path:subpath>/<code>
@handle_db_disconnect
def login_callback():
Helper_App.console_log('login_callback')
try:
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()
# Helper_App.console_log(f'code: {code}')
token = None
try:
token = oauth.auth0.authorize_access_token()
except Exception as e:
# Log the error for debugging
Helper_App.console_log(f"Error: {str(e)}")
session[current_app.config['ID_TOKEN_USER']] = token
# import user id
"""
Helper_App.console_log(f'str(type(token)) = {str(type(token))}')
Helper_App.console_log(f'token = {token}')
userinfo = token.get('userinfo')
Helper_App.console_log(f'user info: {userinfo}')
# id_user = token.get('sub')
id_user = userinfo.get('sub')
Helper_App.console_log(f'user ID: {id_user}')
"""
user = User.from_json_auth0(token) # datastore_user.get_user_auth0()
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 # .get('hash_callback')
Helper_App.console_log(f'hash_callback: {hash_callback}')
except:
Helper_App.console_log("get hash callback failed")
# id_user = get_id_user()
# add user to database
# DataStore_Store().add_new_user(id_user) # this is part of get basket - should occur on page load
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'],
}# ,
# quote_via=quote_plus,
)
Helper_App.console_log(f"Redirecting to {url_logout}")
return redirect(url_logout)
@routes_user.route("/logout_callback") # <path:subpath>/<code>
@handle_db_disconnect
def logout_callback():
return redirect(url_for('routes_core.home'))
try:
session[current_app.ID_TOKEN_USER] = None
user = User()
try:
hash_callback = token.get('hash_callback')
if hash_callback is None:
Helper_App.console_log('hash is none')
state = request.args.get('state')
Helper_App.console_log(f'state: {state}')
hash_callback = state # .get('hash_callback')
Helper_App.console_log(f'hash_callback: {hash_callback}')
except:
Helper_App.console_log("get hash callback failed")
# id_user = get_id_user()
# add user to database
# DataStore_Store().add_new_user(id_user) # this is part of get basket - should occur on page load
Helper_App.console_log(f'user session: {session[Model_View_Base.FLAG_USER]}')
return redirect(f'{current_app.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("/user")
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_user.login', data = jsonify({ Model_View_User.FLAG_CALLBACK: Model_View_User.HASH_PAGE_USER_ACCOUNT })))
return redirect(url_for('routes_core.home'))
html_body = render_template('pages/user/_user.html', model = model)
except Exception as e:
return str(e)
return html_body

View File

@@ -13,11 +13,8 @@ Datastore for Store
# internal
# from routes import bp_home
import lib.argument_validation as av
from business_objects.access_level import Access_Level
from business_objects.region import Region
from business_objects.sql_error import SQL_Error
from business_objects.unit_measurement import Unit_Measurement
from business_objects.user import User, Parameters_User, User_Permission_Evaluation
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
@@ -25,52 +22,26 @@ from forms.access_level import Filters_Access_Level
from forms.unit_measurement import Filters_Unit_Measurement
from helpers.helper_app import Helper_App
# 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
import time
from sqlalchemy.exc import OperationalError
# db = SQLAlchemy()
class DataStore_Base(BaseModel):
# Global constants
# Attributes
"""
app: Flask = None
db: SQLAlchemy = None
session: object = None
"""
# model_config = ConfigDict(arbitrary_types_allowed=True)
def __init__(self, **kwargs):
super().__init__(**kwargs)
# Constructor
"""
self.db = db
self.app = current_app
with self.app.app_context():
self.session = session
"""
@staticmethod
def db_procedure_execute(proc_name, argument_dict_list = None):
# Argument validation
_m = 'DataStore_Base.db_procedure_execute'
av.val_str(proc_name, 'proc_name', _m)
has_arguments = not str(type(argument_dict_list)) == "<class 'NoneType'>"
if has_arguments:
# av.val_list_instances(argument_dict_list, 'argument_dict_list', _m, dict)
pass
# Methods
proc_string = f'CALL {proc_name}('
has_arguments = not str(type(argument_dict_list)) == "<class 'NoneType'>"
if has_arguments:
arg_keys = list(argument_dict_list.keys())
for i in range(len(arg_keys)):
@@ -79,9 +50,6 @@ class DataStore_Base(BaseModel):
proc_string = text(proc_string)
Helper_App.console_log(f'{_m}\nproc_string: {proc_string}\nargs: {argument_dict_list}')
# with self.db.session.begin() as session:
# conn = Helper_DB_MySQL(self.app).get_db_connection()
if has_arguments:
result = db.session.execute(proc_string, argument_dict_list)
else:
@@ -89,114 +57,19 @@ class DataStore_Base(BaseModel):
Helper_App.console_log(f'result: {result}')
# conn.session.remove()
return result
cursor = result.cursor
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'categories: {result_set_1}')
cursor.nextset()
result_set_2 = cursor.fetchall()
Helper_App.console_log(f'products: {result_set_2}')
@staticmethod
def db_cursor_clear(cursor):
while cursor.nextset():
Helper_App.console_log(f'new result set: {cursor.fetchall()}')
@classmethod
def get_many_region_and_currency(cls):
_m = 'DataStore_Base.get_many_region_and_currency'
_m_db_currency = 'p_shop_get_many_currency'
_m_db_region = 'p_shop_get_many_region'
argument_dict_list_currency = {
'a_get_inactive_currency': 0
}
argument_dict_list_region = {
'a_get_inactive_currency': 0
}
Helper_App.console_log(f'executing {_m_db_currency}')
result = cls.db_procedure_execute(_m_db_currency, argument_dict_list_currency)
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
currencies = []
for row in result_set_1:
currency = Currency.make_from_DB_currency(row)
currencies.append(currency)
Helper_App.console_log(f'currencies: {currencies}')
DataStore_Base.db_cursor_clear(cursor)
Helper_App.console_log(f'executing {_m_db_region}')
result = cls.db_procedure_execute(_m_db_region, argument_dict_list_region)
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
regions = []
for row in result_set_1:
region = Region.make_from_DB_region(row)
regions.append(region)
Helper_App.console_log(f'regions: {regions}')
DataStore_Base.db_cursor_clear(cursor)
cursor.close()
return regions, currencies
@staticmethod
def get_user_session():
Helper_App.console_log('DataStore_Base.get_user_session')
user = User.from_json(session.get(User.FLAG_USER))
if user.is_logged_in:
filters_user = Parameters_User.get_default()
filters_user.ids_user = user.id_user
users = DataStore_Base.get_many_user(filters_user)
if user.id_user <= 0:
user.id_user = 3
return user
@classmethod
def get_many_user(cls, filters=None):
_m = 'DataStore_Store_Base.get_many_access_level'
user = User.from_json(session.get(User.FLAG_USER))
if filters is None:
filters_user = Parameters_User.get_default()
filters_user.ids_user = user.id_user if user.is_logged_in else None
av.val_instance(filters, 'filters', _m, Parameters_User)
argument_dict = filters.to_json()
argument_dict = {
'a_id_user': user.id_user,
'a_id_user_auth0': user.id_user_auth0,
**argument_dict,
'a_debug': 0,
}
Helper_App.console_log(f'argument_dict: {argument_dict}')
Helper_App.console_log('executing p_get_many_user')
result = cls.db_procedure_execute('p_get_many_user', argument_dict)
cursor = result.cursor
Helper_App.console_log('data received')
# users
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw users: {result_set_1}')
users = []
for row in result_set_1:
new_user = User.from_DB_user(row)
users.append(new_user)
# 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] # (row[0], row[1])
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
DataStore_Base.db_cursor_clear(cursor)
cursor.close()
return users, errors
@staticmethod
def upload_bulk(permanent_table_name, records, batch_size):
@@ -214,30 +87,6 @@ class DataStore_Base(BaseModel):
else:
expected_columns = set(column.name for column in db.inspect(table_object).columns)
Helper_App.console_log(f'expected_columns: {expected_columns}')
""" v1, v2
try:
for i in range(0, len(records), batch_size):
"" v1
batch = records[i:i+batch_size]
Helper_App.console_log(f'batch: {batch}')
db.session.bulk_save_objects(batch)
""
""
data = [object.to_json() for object in batch]
Helper_App.console_log(f'data: {data}')
for row in data:
row_keys = set(row.keys())
if row_keys != expected_columns:
Helper_App.console_log(f"Column mismatch in row: {row}")
Helper_App.console_log(f'missing columns: {expected_columns - row_keys}')
Helper_App.console_log(f'extra columns: {row_keys - expected_columns}')
# db.session.bulk_insert_mappings(permanent_table_name, data)
""
except Exception as e:
Helper_App.console_log(f'{_m}\n{e}')
db.session.rollback()
raise e
"""
max_retries = 3
initial_backoff = 1
for i in range(0, len(records), batch_size):
@@ -263,104 +112,3 @@ class DataStore_Base(BaseModel):
except Exception as e:
db.session.rollback()
raise e
@classmethod
def get_many_access_level(cls, filters=None):
_m = 'DataStore_Store_Base.get_many_access_level'
if filters is None:
filters = Filters_Access_Level()
av.val_instance(filters, 'filters', _m, Filters_Access_Level)
argument_dict = filters.to_json()
# user = cls.get_user_session()
# argument_dict['a_id_user'] = 1 # 'auth0|6582b95c895d09a70ba10fef' # id_user
Helper_App.console_log(f'argument_dict: {argument_dict}')
Helper_App.console_log('executing p_shop_get_many_access_level')
result = cls.db_procedure_execute('p_shop_get_many_access_level', argument_dict)
cursor = result.cursor
Helper_App.console_log('data received')
# access_levels
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw access levels: {result_set_1}')
access_levels = []
for row in result_set_1:
new_access_level = Access_Level.from_DB_access_level(row)
access_levels.append(new_access_level)
# 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] # (row[0], row[1])
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
DataStore_Base.db_cursor_clear(cursor)
cursor.close()
return access_levels, errors
@classmethod
def get_many_unit_measurement(cls, filters=None):
_m = 'DataStore_Store_Base.get_many_unit_measurement'
if filters is None:
filters = Filters_Unit_Measurement()
av.val_instance(filters, 'filters', _m, Filters_Unit_Measurement)
argument_dict = filters.to_json()
# user = cls.get_user_session()
# argument_dict['a_id_user'] = 1 # 'auth0|6582b95c895d09a70ba10fef' # id_user
Helper_App.console_log(f'argument_dict: {argument_dict}')
Helper_App.console_log('executing p_shop_get_many_unit_measurement')
result = cls.db_procedure_execute('p_shop_get_many_unit_measurement', argument_dict)
cursor = result.cursor
Helper_App.console_log('data received')
# units of measurement
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw units of measurement: {result_set_1}')
units = []
for row in result_set_1:
new_unit = Unit_Measurement.from_DB_unit_measurement(row)
units.append(new_unit)
# 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] # (row[0], row[1])
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
DataStore_Base.db_cursor_clear(cursor)
cursor.close()
return units, errors
@classmethod
def get_many_region(cls, get_inactive = False):
_m = 'DataStore_Store_Base.get_many_region'
_m_db_region = 'p_shop_get_many_region'
argument_dict_list_region = {
'a_get_inactive_region': 1 if get_inactive else 0
}
Helper_App.console_log(f'executing {_m_db_region}')
result = cls.db_procedure_execute(_m_db_region, argument_dict_list_region)
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
regions = []
for row in result_set_1:
region = Region.from_DB_region(row)
regions.append(region)
Helper_App.console_log(f'regions: {regions}')
DataStore_Base.db_cursor_clear(cursor)
cursor.close()
return regions

View File

@@ -1,351 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: DataStores
Feature: Base Store DataStore
Description:
Datastore for Store
"""
# internal
# from routes import bp_home
from business_objects.store.basket import Basket, Basket_Item
from business_objects.store.product_category import Product_Category_Container, Product_Category
from business_objects.currency import Currency
from business_objects.store.image import Image
from business_objects.store.delivery_option import Delivery_Option
from business_objects.region import Region
from business_objects.store.discount import Discount
from business_objects.store.order import Order
from business_objects.store.plant import Plant
from business_objects.store.product import Product, Product_Permutation, Parameters_Product
from business_objects.sql_error import SQL_Error
from business_objects.store.stock_item import Stock_Item
from business_objects.store.storage_location import Storage_Location
from business_objects.store.product_variation import Product_Variation, Parameters_Product_Variation
from business_objects.store.product_variation_type import Product_Variation_Type
from datastores.datastore_base import DataStore_Base
from extensions import db
from helpers.helper_app import Helper_App
from helpers.helper_db_mysql import Helper_DB_MySQL
import lib.argument_validation as av
# from models.model_view_store_checkout import Model_View_Store_Checkout # circular!
# 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_Store_Base(DataStore_Base):
# Global constants
KEY_BASKET: ClassVar[str] = Basket.KEY_BASKET
KEY_IS_INCLUDED_VAT: ClassVar[str] = Basket.KEY_IS_INCLUDED_VAT # 'is_included_VAT'
KEY_ID_CURRENCY: ClassVar[str] = Basket.KEY_ID_CURRENCY # 'id_currency'
KEY_ID_REGION_DELIVERY: ClassVar[str] = Basket.KEY_ID_REGION_DELIVERY # 'id_region_delivery'
# Attributes
def __init__(self, **kwargs):
super().__init__(**kwargs)
@classmethod
def get_many_product(cls, product_filters):
# redundant argument validation?
_m = 'DataStore_Store_Base.get_many_product'
av.val_instance(product_filters, 'product_filters', _m, Parameters_Product)
argument_dict = product_filters.to_json()
user = cls.get_user_session()
"""
argument_dict['a_id_user'] = user.id_user # 'auth0|6582b95c895d09a70ba10fef' # id_user
argument_dict['a_debug'] = 0
"""
argument_dict = {
'a_id_user': user.id_user
, **argument_dict
, 'a_debug': 0
}
Helper_App.console_log(f'argument_dict: {argument_dict}')
Helper_App.console_log('executing p_shop_get_many_product')
result = cls.db_procedure_execute('p_shop_get_many_product', argument_dict)
cursor = result.cursor
Helper_App.console_log('data received')
category_list = Product_Category_Container()
Helper_App.console_log(f'initial category_list: {category_list}')
# Categories
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw categories: {result_set_1}')
for row in result_set_1:
new_category = Product_Category.from_DB_get_many_product_catalogue(row)
Helper_App.console_log(f'new_category: {new_category}')
category_list.add_product_category(new_category)
Helper_App.console_log(f'category-loaded category_list: {category_list}')
# Products
cursor.nextset()
result_set_2 = cursor.fetchall()
Helper_App.console_log(f'raw products: {result_set_2}')
for row in result_set_2:
Helper_App.console_log(f'row: {row}')
new_product = Product.from_DB_get_many_product_catalogue(row)
Helper_App.console_log(f'new_product: {new_product}')
try:
category_list.add_product(new_product)
except Exception as e:
Helper_App.console_log(f'Error adding product: {e}')
# Permutations
cursor.nextset()
result_set_3 = cursor.fetchall()
for row in result_set_3:
new_permutation = Product_Permutation.from_DB_get_many_product_catalogue(row)
try:
category_list.add_product_permutation(new_permutation)
except Exception as e:
Helper_App.console_log(f'Error adding permutation: {e}')
# Product_Variations
cursor.nextset()
result_set_4 = cursor.fetchall()
for row in result_set_4:
new_variation_type = Product_Variation_Type.from_DB_get_many_product_catalogue(row)
try:
category_list.add_product_variation_type(new_variation_type)
except Exception as e:
Helper_App.console_log(f'Error adding variation: {e}')
# Images
cursor.nextset()
result_set_5 = cursor.fetchall()
for row in result_set_5:
new_image = Image.from_DB_get_many_product_catalogue(row)
category_list.add_product_image(new_image)
# 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] # (row[0], row[1])
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
category_list.get_all_product_variation_trees()
"""
for category in category_list.categories:
Helper_App.console_log(f'category: {category.name}')
for product in category.products:
permutation = product.get_permutation_selected()
Helper_App.console_log(f'product: {product.name}\nselected permutation: {permutation}')
"""
if len(errors) > 0:
for error in errors:
if error.code == 'PRODUCT_AVAILABILITY':
ids_permutation_unavailable = DataStore_Store_Base.get_ids_permutation_from_error_availability(error.msg)
for id_permutation in ids_permutation_unavailable:
index_category = category_list.get_index_category_from_id_permutation(id_permutation)
category = category_list.categories[index_category]
index_product = category.get_index_product_from_id_permutation(id_permutation)
product = category.products[index_product]
index_permutation = product.get_index_permutation_from_id(id_permutation)
permutation = product.permutations[index_permutation]
permutation.is_available = False
if 'region' in error.msg or 'currency' in error.msg:
permutation.is_unavailable_in_currency_or_region = True
DataStore_Store_Base.db_cursor_clear(cursor)
cursor.close()
Helper_App.console_log(f'get many category_list: {category_list}')
return category_list, errors # categories, category_index
"""
def get_many_id_price(self, product_ids):
_m = 'DataStore_Store_Base.get_many_id_price'
av.val_str(product_ids, 'product_ids', _m)
price_ids = []
for product_id in product_ids.split(','):
if product_id == 'prod_PB0NUOSEs06ymG':
price_ids.append() # get price id
return price_ids
"""
@staticmethod
def get_ids_permutation_from_error_availability(msg_error_availability):
ids_permutation = []
index_colon = msg_error_availability.find(':', msg_error_availability.find(':'))
msg_error_availability = msg_error_availability[index_colon + 1:]
index_comma = 0
while index_comma > -1:
msg_error_availability = msg_error_availability[index_comma:]
index_comma = msg_error_availability.find(',')
ids_permutation.append(msg_error_availability[:index_comma])
return ids_permutation
@classmethod
def get_many_plant(cls, get_inactive = False):
_m = 'DataStore_Store_Base.get_many_plant'
_m_db_plant = 'p_shop_get_many_plant'
argument_dict_list_plant = {
'a_get_inactive_plant': 1 if get_inactive else 0
}
Helper_App.console_log(f'executing {_m_db_plant}')
result = cls.db_procedure_execute(_m_db_plant, argument_dict_list_plant)
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
plants = []
for row in result_set_1:
plant = Plant.from_DB_plant(row)
plants.append(plant)
Helper_App.console_log(f'plants: {plants}')
DataStore_Store_Base.db_cursor_clear(cursor)
cursor.close()
return plants
@classmethod
def get_many_storage_location(self, get_inactive = False):
_m = 'DataStore_Store_Base.get_many_storage_location'
_m_db_storage_location = 'p_shop_get_many_storage_location'
argument_dict_list_storage_location = {
'a_get_inactive_storage_location': 1 if get_inactive else 0
}
Helper_App.console_log(f'executing {_m_db_storage_location}')
result = self.db_procedure_execute(_m_db_storage_location, argument_dict_list_storage_location)
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
storage_locations = []
for row in result_set_1:
storage_location = Storage_Location.from_DB_storage_location(row)
storage_locations.append(storage_location)
Helper_App.console_log(f'storage_locations: {storage_locations}')
DataStore_Store_Base.db_cursor_clear(cursor)
cursor.close()
return storage_locations
@classmethod
def get_many_currency(cls, get_inactive = False):
_m = 'DataStore_Store_Base.get_many_currency'
_m_db_currency = 'p_shop_get_many_currency'
argument_dict_list_currency = {
'a_get_inactive_currency': 1 if get_inactive else 0
}
Helper_App.console_log(f'executing {_m_db_currency}')
result = cls.db_procedure_execute(_m_db_currency, argument_dict_list_currency)
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
currencies = []
for row in result_set_1:
currency = Currency.from_DB_currency(row)
currencies.append(currency)
Helper_App.console_log(f'currencies: {currencies}')
DataStore_Store_Base.db_cursor_clear(cursor)
return currencies
@classmethod
def get_many_region_and_currency(cls, get_inactive_currency = False, get_inactive_region = False):
_m = 'DataStore_Store_Base.get_many_region_and_currency'
currencies = cls.get_many_currency(get_inactive_currency)
regions = cls.get_many_region(get_inactive_region)
return regions, currencies
@classmethod
def get_many_product_variation(cls, variation_filters):
_m = 'DataStore_Store_Base.get_many_product_variation'
Helper_App.console_log(_m)
av.val_instance(variation_filters, 'variation_filters', _m, Parameters_Product_Variation)
guid = Helper_DB_MySQL.create_guid()
# now = datetime.now()
# user = self.get_user_session()
"""
argument_dict_list = {
'a_id_user': id_user,
'a_comment': comment,
'a_guid': guid
}
"""
user = cls.get_user_session()
argument_dict_list = {
# 'a_guid': guid
'a_id_user': user.id_user
, **variation_filters.to_json()
, 'a_debug': 0
}
# argument_dict_list['a_guid'] = guid
result = cls.db_procedure_execute('p_shop_get_many_product_variation', argument_dict_list)
cursor = result.cursor
result_set_vt = cursor.fetchall()
# Product_Variation Types
# variation_container = Product_Variation_Container()
variation_types = []
index_variation_type = {}
for row in result_set_vt:
new_variation_type = Product_Variation_Type.from_DB_get_many_product_variation(row)
# variation_container.add_product_variation_type(new_variation_type)
index_variation_type[new_variation_type.id_type] = len(variation_types)
variation_types.append(new_variation_type)
Helper_App.console_log(f'index_variation_type: {index_variation_type}')
# Product_Variations
cursor.nextset()
result_set_v = cursor.fetchall()
# variations = Product_Variation_Container()
variations = []
for row in result_set_v:
new_variation = Product_Variation.from_DB_get_many_product_variation(row)
# new_variation.variation_type = variation_types_dict[new_variation.id_type]
# variation_container.add_product_variation(new_variation)
variation_types[index_variation_type[new_variation.id_type]].variations.append(new_variation)
variations.append(new_variation)
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] # [SQL_Error(row[0], row[1]) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
DataStore_Store_Base.db_cursor_clear(cursor)
cursor.close()
return variation_types, variations, errors

View File

@@ -1,195 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: DataStores
Feature: Store Stripe DataStore
Description:
Datastore for Store Stripe service
"""
# internal
# from routes import bp_home
import lib.argument_validation as av
from business_objects.store.basket import Basket, Basket_Item
from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product
from business_objects.sql_error import SQL_Error
from datastores.datastore_store_base import DataStore_Store_Base
# 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 helpers.helper_app import Helper_App
# 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_Store_Stripe(DataStore_Store_Base):
# Global constants
# Attributes
key_public_stripe: str = None
key_secret_stripe: str = None
def __init__(self):
super().__init__()
self.key_secret_stripe = os.environ.get("KEY_SECRET_STRIPE")
self.key_public_stripe = os.environ.get("KEY_PUBLIC_STRIPE")
# For sample support and debugging, not required for production:
stripe.set_app_info(
'stripe-samples/checkout-one-time-payments',
version='0.0.1',
url='https://github.com/stripe-samples/checkout-one-time-payments')
stripe.api_key = self.key_secret_stripe
def get_many_stripe_product_new(self):
_m = 'DataStore_Store_Stripe.get_many_stripe_product_new'
_m_db = 'p_shop_get_many_stripe_product_new'
# av.val_str(id_user)
# validation conducted by server
argument_dict_list = {
'a_id_user': self.info_user
}
Helper_App.console_log(f'executing {_m_db}')
result = self.db_procedure_execute(_m_db, argument_dict_list)
cursor = result.cursor
Helper_App.console_log('data received')
# Products
cursor.nextset()
result_set_1 = cursor.fetchall()
products = []
for row in result_set_1:
new_product = Product.from_DB_Stripe_product(row) # Product(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19])
products.append(new_product)
Helper_App.console_log(f'products: {products}')
# 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] # [SQL_Error(row[0], row[1]) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
DataStore_Store_Stripe.db_cursor_clear(cursor)
return products
def get_many_stripe_price_new(self):
_m = 'DataStore_Store_Stripe.get_many_stripe_price_new'
_m_db = 'p_shop_get_many_stripe_price_new'
# av.val_str(id_user)
# validation conducted by server
argument_dict_list = {
'a_id_user': self.info_user
}
Helper_App.console_log(f'executing {_m_db}')
result = self.db_procedure_execute(_m_db, argument_dict_list)
cursor = result.cursor
Helper_App.console_log('data received')
# Products
cursor.nextset()
result_set_1 = cursor.fetchall()
products = []
for row in result_set_1:
new_product = Product.from_DB_Stripe_price(row) # Product(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19])
products.append(new_product)
Helper_App.console_log(f'products: {products}')
# 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] # [SQL_Error(row[0], row[1]) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
DataStore_Store_Stripe.db_cursor_clear(cursor)
return products
def get_many_product_new(self):
_m = 'DataStore_Store_Stripe.get_many_product_new'
# Stripe
new_products = self.get_many_stripe_product_new()
for product in new_products:
product.id_stripe_product = self.create_stripe_product(product)
return new_products
def get_many_price_new(self):
_m = 'DataStore_Store_Stripe.get_many_product_new'
# Stripe
new_products = self.get_many_stripe_price_new()
for product in new_products:
product.id_stripe_price = self.create_stripe_price(product)
return new_products
# Stripe
def create_stripe_product(self, product): # _name, product_description):
_m = 'DataStore_Store_Stripe_Checkout.create_stripe_product'
# av.val_str(product_name, 'product_name', _m)
# av.val_str(product_description, 'product_description', _m)
av.val_instance(product, 'product', _m, Product)
Helper_App.console_log(f'stripe.api_key = {stripe.api_key}')
new_product = stripe.Product.create(
name = product.name,
description = product.description,
)
# Save these identifiers
Helper_App.console_log(f"Success! Here is your new Stripe product id: {new_product.id}")
return new_product.id
def create_stripe_price(self, product, currency): # product_id, product_price, product_currency, product_is_subscription, product_recurring_interval = '', product_interval_count = 0):
_m = 'DataStore_Store_Stripe_Checkout.create_stripe_price'
"""
av.val_str(p_id, 'p_id', _m)
av.full_val_float(p_price, 'p_price', _m, 0.01)
p_price = round(p_price, 2)
av.val_str(p_currency, 'p_currency', _m)
av.full_val_bool(p_is_subscription, 'p_is_subscription', _m)
p_is_subscription = bool(p_is_subscription)
av.val_str(p_recurring_interval, 'p_recurring_interval', _m)
av.full_val_int(p_interval_count, 'p_interval_count', _m, 1 if p_is_subscription else 0)
p_interval_count = int(p_interval_count)
"""
av.val_instance(product, 'product', _m, Product)
av.val_str(currency, 'currency', _m)
Helper_App.console_log(f'stripe.api_key = {stripe.api_key}')
new_product_price = stripe.Price.create(
unit_amount = product.unit_price,
currency = currency,
recurring = { "interval": product.name_recurring_interval, "interval_count": product.count_recurring_interval } if product.is_subscription else None,
product = product.id_stripe_product
)
# Save these identifiers
Helper_App.console_log(f"Success! Here is your Stripe product price id: {new_product_price.id} for {product.name}")
return new_product_price.id

View File

@@ -1,251 +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.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):
# Global constants
# Attributes
def __init__(self):
super().__init__()
def edit_user(self):
# redundant argument validation?
_m = 'DataStore_User.edit_user'
# av.val_instance(filters, 'filters', _m, Filters_Product_Category)
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_shop_edit_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] # [SQL_Error(row[0], row[1]) for row in result_set_2]
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_order(self, id_user, ids_order, n_order_max, id_checkout_session):
_m = 'DataStore_User.get_many_user_order'
# av.val_str(id_user)
# validation conducted by server
argument_dict_list = {
'a_id_user': id_user,
'a_ids_order': ids_order,
'a_n_order_max': n_order_max,
'a_id_checkout_session': id_checkout_session
}
Helper_App.console_log('executing p_shop_get_many_user_order')
result = self.db_procedure_execute('p_shop_get_many_user_order', argument_dict_list)
cursor = result.cursor
Helper_App.console_log('data received')
# Discount Delivery Regions
cursor.nextset()
result_set_1 = cursor.fetchall()
orders = []
for row in result_set_1:
new_order = Order(row[0], row[1], row[2], row[3], row[4], row[5], row[6])
orders.append(new_order)
Helper_App.console_log(f'orders: {orders}')
# 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] # [SQL_Error(row[0], row[1]) 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 orders
"""
def get_many_user(self, user_filters, user=None):
_m = 'DataStore_User.get_many_user'
Helper_App.console_log(_m)
# av.val_str(user_filters, 'user_filters', _m)
# av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1)
av.val_instance(user_filters, 'user_filters', _m, Parameters_User)
guid = Helper_DB_MySQL.create_guid()
# now = datetime.now()
# user = self.get_user_session()
"""
argument_dict_list = {
'a_id_user': id_user,
'a_comment': comment,
'a_guid': guid
}
"""
if user is None:
user = self.get_user_session()
argument_dict_list = {
# 'a_guid': guid
'a_id_user': user.id_user
, 'a_id_user_auth0': user.id_user_auth0
, **user_filters.to_json()
, 'a_debug': 0
}
# argument_dict_list['a_guid'] = guid
result = self.db_procedure_execute('p_get_many_user', argument_dict_list)
"""
query = text(f"SELECT * FROM Shop_Calc_User_Temp UE_T WHERE UE_T.guid = '{guid}'")
result = self.db.session.execute(query)
"""
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)}')
"""
user_permission_evals = []
for row in result_set:
user_permission_eval = User_Permission_Evaluation.from_DB_user_eval(row)
user_permission_evals.append(user_permission_eval)
Helper_App.console_log(f'user_permission_evals: {user_permission_evals}')
"""
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]))}')
# error_list, cursor = self.get_error_list_from_cursor(cursor)
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] # [SQL_Error(row[0], row[1]) 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 users, errors
def get_many_user(self, user_filters, user=None):
_m = 'DataStore_User.get_many_user'
Helper_App.console_log(_m)
# av.val_str(user_filters, 'user_filters', _m)
# av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1)
av.val_instance(user_filters, 'user_filters', _m, Parameters_User)
guid = Helper_DB_MySQL.create_guid()
# now = datetime.now()
# user = self.get_user_session()
"""
argument_dict_list = {
'a_id_user': id_user,
'a_comment': comment,
'a_guid': guid
}
"""
if user is None:
user = self.get_user_session()
argument_dict_list = {
# 'a_guid': guid
'a_id_user': user.id_user
, 'a_id_user_auth0': user.id_user_auth0
, **user_filters.to_json()
, 'a_debug': 0
}
# argument_dict_list['a_guid'] = guid
result = self.db_procedure_execute('p_get_many_user', argument_dict_list)
"""
query = text(f"SELECT * FROM Shop_Calc_User_Temp UE_T WHERE UE_T.guid = '{guid}'")
result = self.db.session.execute(query)
"""
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)}')
"""
user_permission_evals = []
for row in result_set:
user_permission_eval = User_Permission_Evaluation.from_DB_user_eval(row)
user_permission_evals.append(user_permission_eval)
Helper_App.console_log(f'user_permission_evals: {user_permission_evals}')
"""
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]))}')
# error_list, cursor = self.get_error_list_from_cursor(cursor)
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] # [SQL_Error(row[0], row[1]) 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 users, errors

View File

@@ -0,0 +1,113 @@
"""
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.contact_form import Contact_Form, Contact_Form_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_Contact_Form(DataStore_Base):
def __init__(self):
super().__init__()
@classmethod
def get_many_contact_form(cls):
_m = f'{cls.__qualname__}.get_many_contact_form'
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_contact_form', argument_dict)
cursor = result.cursor
# Contact_Forms
result_set_1 = cursor.fetchall()
Helper_App.console_log(f'raw contact_forms: {result_set_1}')
contact_forms = []
contact_form_indexes = {}
for row in result_set_1:
new_contact_form = Contact_Form.from_DB_contact_form(row)
contact_form_indexes[new_contact_form.id_contact_form] = len(contact_forms)
contact_forms.append(new_contact_form)
# 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 contact_forms, errors
@classmethod
def save_contact_forms(cls, comment, contact_forms):
_m = f'{cls}.save_contact_forms'
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 contact forms: {contact_forms}')
rows = []
for contact_form in contact_forms:
row = Contact_Form_Temp.from_contact_form(contact_form)
row.guid = guid
rows.append(row)
cls.upload_bulk(Contact_Form_Temp.__tablename__, rows, 1000)
Helper_App.console_log('Contact Forms 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_contact_form', argument_dict_list)
Helper_App.console_log('Contact Forms 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

@@ -8,7 +8,7 @@ from authlib.integrations.flask_client import OAuth
csrf = CSRFProtect()
cors = CORS()
# cors = CORS()
db = SQLAlchemy()
mail = Mail()
oauth = OAuth()

View File

@@ -12,22 +12,89 @@ Defines Flask-WTF form for handling user input on Contact Us page.
# IMPORTS
# internal
# from business_objects.store.product_category import Filters_Product_Category # circular
from business_objects.base import Base
from business_objects.project_hub.contact_form import Contact_Form
# 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, BooleanField, IntegerField, SelectField, FloatField
from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional
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 = StringField('Email')
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()
# 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
, Contact_Form.FLAG_NAME_CONTACT: self.contact_name.data
, Contact_Form.FLAG_NAME_COMPANY: self.company_name.data
, Contact_Form.FLAG_MESSAGE: self.message.data
, Contact_Form.FLAG_RECEIVE_MARKETING_COMMUNICATIONS: self.receive_marketing.data
, Contact_Form.FLAG_ALTCHA: self.altcha.data
, Base.FLAG_ACTIVE: True
, Base.FLAG_CREATED_ON: None
}

View File

@@ -31,7 +31,7 @@ def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_c
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
error_msg = error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "<class 'bool'>", suppress_errors)
if suppress_errors:
print(error_msg)
Helper_App.console_log(error_msg)
return error_msg
else:
raise ValueError(error_msg)
@@ -40,7 +40,7 @@ def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_c
error_msg = error_msg_str(method, 'method', my_f, "<class 'str'>", suppress_errors, suppress_console_outputs)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return error_msg
else:
raise ValueError(error_msg)
@@ -50,7 +50,7 @@ def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_c
error_msg = error_msg_str(v_name, 'v_name', my_f, "<class 'str'>", suppress_errors, suppress_console_outputs)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return error_msg
else:
raise ValueError(error_msg)
@@ -61,7 +61,7 @@ def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_c
error_msg = error_msg_str(v_type, 'v_type', my_f, "<class 'str'>", suppress_errors, suppress_console_outputs)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return error_msg
else:
raise ValueError(error_msg)
@@ -70,7 +70,7 @@ def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_c
error_msg = error_msg_str(v_arg_type, 'v_arg_type', my_f, "<class 'str'>", suppress_errors, suppress_console_outputs)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return error_msg
else:
raise ValueError(error_msg)
@@ -96,7 +96,7 @@ def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_
if str(type(suppress_console_outputs)) != v_type:
error_msg = error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, v_type, suppress_errors)
if suppress_errors:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
v_type = "<class 'str'>"
@@ -111,7 +111,7 @@ def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_
error_msg = error_msg_str(method, 'method', my_f, v_type, suppress_errors, suppress_console_outputs)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
my_f = method + '.' + my_f
@@ -126,7 +126,7 @@ def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_
error_msg = error_msg_str(v_name, 'v_name', my_f, v_type, suppress_errors, suppress_console_outputs)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# v_arg_type
@@ -140,7 +140,7 @@ def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_
error_msg = error_msg_str(v_arg_type, 'v_arg_type', my_f, v_type, suppress_errors, suppress_console_outputs)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
else:
raise ValueError(error_msg)
@@ -150,7 +150,7 @@ def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_
error_msg = error_msg_str(v_input, v_name, method, v_type, suppress_errors, suppress_console_outputs)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# RETURNS
@@ -176,7 +176,7 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
val_bool(suppress_errors, 'suppress_errors', my_f)
# suppress_console_outputs
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
print(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "<class 'bool'>", suppress_errors))
Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "<class 'bool'>", suppress_errors))
return False
# method
valid = True
@@ -189,7 +189,7 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
error_msg = error_msg_str(method, 'method', my_f, v_type)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
my_f = method + '.' + my_f
@@ -204,7 +204,7 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
error_msg = error_msg_str(v_name, 'v_name', my_f, v_type)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# v_arg_type
@@ -218,7 +218,7 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
error_msg = error_msg_str(v_arg_type, 'v_arg_type', my_f, v_type)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# min_len
@@ -227,7 +227,7 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
error_msg = error_msg_str(min_len, 'min_len', my_f, v_type)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# max_len
@@ -242,7 +242,7 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
error_msg = error_msg_str(max_len, 'max_len', my_f, v_type)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# v_input
@@ -256,15 +256,15 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
L = len(v_input)
if min_len != -1 and L < min_len:
valid = False
print(f"Minimum str length {min_len} not met.")
Helper_App.console_log(f"Minimum str length {min_len} not met.")
if max_len != -1 and L > max_len:
print(f"Maximum str length {max_len} not met.")
Helper_App.console_log(f"Maximum str length {max_len} not met.")
valid = False
if not valid:
error_msg = error_msg_str(v_input, v_name, method, v_type, suppress_errors, suppress_console_outputs, v_arg_type)
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# RETURNS
@@ -297,7 +297,7 @@ def val_int(v_input, v_name, method, v_min: Optional[int] = None, v_max: Optiona
val_bool(suppress_errors, 'suppress_errors', my_f)
# suppress_console_outputs
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
print(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "<class 'bool'>", suppress_errors))
Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "<class 'bool'>", suppress_errors))
return False
# method
if not val_str(method, 'method', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False
@@ -322,28 +322,28 @@ def val_int(v_input, v_name, method, v_min: Optional[int] = None, v_max: Optiona
if not mytype == str(type(v_input)):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
if (v_min != None and v_max != None):
if (v_min > v_max):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.")
Helper_App.console_log(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.")
return False
raise ValueError(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.")
if (v_min != None):
if (v_input < v_min):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg + f"\nValue less than minimum {v_min}.")
Helper_App.console_log(error_msg + f"\nValue less than minimum {v_min}.")
return False
raise ValueError(error_msg + f"\nValue less than minimum {v_min}.")
if (v_max != None):
if (v_input > v_max):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg + f"\nValue greater than maximum {v_max}.")
Helper_App.console_log(error_msg + f"\nValue greater than maximum {v_max}.")
return False
raise ValueError(error_msg + f"\nValue greater than maximum {v_max}.")
# RETURNS
@@ -368,7 +368,7 @@ def val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_erro
val_bool(suppress_errors, 'suppress_errors', my_f)
# suppress_console_outputs
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
print(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "<class 'bool'>", suppress_errors))
Helper_App.console_log(error_msg_str(suppress_console_outputs, 'suppress_console_outputs', my_f, "<class 'bool'>", suppress_errors))
return False
# v_name
if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False
@@ -393,28 +393,28 @@ def val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_erro
if not mytype == str(type(v_input)):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
if (v_min != None and v_max != None):
if (v_min > v_max):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.")
Helper_App.console_log(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.")
return False
raise ValueError(error_msg + f"\nInverted minimum and maximum values {v_min} and {v_max}.")
if (v_min != None):
if (v_input < v_min):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg + f"\nValue less than minimum {v_min}.")
Helper_App.console_log(error_msg + f"\nValue less than minimum {v_min}.")
return False
raise ValueError(error_msg + f"\nValue less than minimum {v_min}.")
if (v_max != None):
if (v_input > v_max):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg + f"\nValue greater than maximum {v_max}.")
Helper_App.console_log(error_msg + f"\nValue greater than maximum {v_max}.")
return False
raise ValueError(error_msg + f"\nValue greater than maximum {v_max}.")
# RETURNS
@@ -456,7 +456,7 @@ def input_bool(v_input, v_name, method, suppress_errors = False, suppress_consol
if not val_str(v_input, v_name, my_f, suppress_errors=True, suppress_console_outputs=True):
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return None
raise ValueError(error_msg)
else:
@@ -471,7 +471,7 @@ def input_bool(v_input, v_name, method, suppress_errors = False, suppress_consol
return False
if suppress_errors:
if not suppress_console_outputs:
print(error_msg)
Helper_App.console_log(error_msg)
return None
raise ValueError(error_msg)
else:

View File

@@ -18,9 +18,10 @@ Base data model for views
# internal
# from routes import bp_home
from business_objects.base import Base
from business_objects.user import User, Parameters_User
from business_objects.project_hub.user import User
from business_objects.project_hub.contact_form import Contact_Form
from datastores.datastore_base import DataStore_Base
from datastores.datastore_user import DataStore_User
from datastores.project_hub.datastore_contact_form import DataStore_Contact_Form
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
@@ -35,26 +36,26 @@ from typing import ClassVar
class Model_View_Base(BaseModel, ABC):
# Global constants
# ATTR_FOR: ClassVar[str] = 'for'
ATTR_ID_ACCESS_LEVEL: ClassVar[str] = Base.ATTR_ID_ACCESS_LEVEL
ATTR_ID_ADDRESS: ClassVar[str] = Base.ATTR_ID_ADDRESS
ATTR_ID_CURRENCY: ClassVar[str] = Base.ATTR_ID_CURRENCY
ATTR_ID_REGION: ClassVar[str] = Base.ATTR_ID_REGION
ATTR_TEXT_COLLAPSED: ClassVar[str] = 'textCollapsed'
ATTR_TEXT_EXPANDED: ClassVar[str] = 'textExpanded'
ATTR_VALUE_CURRENT: ClassVar[str] = 'current-value'
ATTR_VALUE_PREVIOUS: ClassVar[str] = 'previous-value'
COMPANY_ADDRESS_SHORT: ClassVar[str] = '53 Alfred Green Close, Rugby, United Kingdom, CV22 6DN'
COMPANY_NUMBER: ClassVar[str] = '13587499'
FLAG_ACCESS_LEVEL: ClassVar[str] = 'access_level'
FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = Base.FLAG_ACCESS_LEVEL_REQUIRED
ENDPOINT_GET_ALTCHA_CHALLENGE: ClassVar[str] = 'routes_core_contact.create_altcha_challenge'
ENDPOINT_PAGE_ACCESSIBILITY_REPORT: ClassVar[str] = 'routes_legal.accessibility_report'
ENDPOINT_PAGE_ACCESSIBILITY_STATEMENT: ClassVar[str] = 'routes_legal.accessibility_statement'
ENDPOINT_PAGE_CONTACT: ClassVar[str] = 'routes_core_contact.contact'
ENDPOINT_PAGE_CONTACT_SUCCESS: ClassVar[str] = 'routes_core_contact.contact_success'
ENDPOINT_PAGE_DATA_RETENTION_SCHEDULE: ClassVar[str] = 'routes_legal.retention_schedule'
ENDPOINT_PAGE_ERROR_NO_PERMISSION: ClassVar[str] = 'routes_core.error_no_permission'
ENDPOINT_PAGE_HOME: ClassVar[str] = 'routes_core_home.home'
ENDPOINT_PAGE_LICENSE: ClassVar[str] = 'routes_legal.license'
ENDPOINT_PAGE_PRIVACY_POLICY: ClassVar[str] = 'routes_legal.privacy_policy'
ENDPOINT_POST_CONTACT_FORM: ClassVar[str] = 'routes_core_contact.contact_post'
FLAG_ACTIVE: ClassVar[str] = Base.FLAG_ACTIVE
FLAG_ADD: ClassVar[str] = 'add'
# FLAG_ADD_DELETE: ClassVar[str] = 'add-delete'
FLAG_ADDRESS: ClassVar[str] = Base.FLAG_ADDRESS
FLAG_ADDRESS_LINE_1: ClassVar[str] = Base.FLAG_ADDRESS_LINE_1
FLAG_ADDRESS_LINE_2: ClassVar[str] = Base.FLAG_ADDRESS_LINE_2
FLAG_BOOL_FALSE: ClassVar[str] = 'false'
FLAG_BOOL_TRUE: ClassVar[str] = 'true'
FLAG_BUTTON: ClassVar[str] = 'button'
@@ -62,29 +63,26 @@ class Model_View_Base(BaseModel, ABC):
FLAG_BUTTON_PRIMARY: ClassVar[str] = 'button-primary'
FLAG_CANCEL: ClassVar[str] = 'button-cancel'
FLAG_CALLBACK: ClassVar[str] = 'callback'
FLAG_CAPTCHA: ClassVar[str] = 'captcha'
FLAG_CARD: ClassVar[str] = 'card'
FLAG_CITY: ClassVar[str] = Base.FLAG_CITY
FLAG_CLOSE_TEMPORARY_ELEMENT: ClassVar[str] = 'button-temporary-element-close'
FLAG_CODE: ClassVar[str] = Base.FLAG_CODE
FLAG_COLLAPSED: ClassVar[str] = 'collapsed'
FLAG_COLLAPSIBLE: ClassVar[str] = 'collapsible'
FLAG_COLUMN: ClassVar[str] = 'column'
FLAG_COMMENT: ClassVar[str] = 'comment'
# FLAG_CONTACT_US: ClassVar[str] = 'button-contact'
FLAG_CONTAINER: ClassVar[str] = 'container'
FLAG_CONTAINER_CHECKBOX: ClassVar[str] = 'container-checkbox'
FLAG_CONTAINER_ICON_AND_LABEL: ClassVar[str] = 'container-icon-label'
FLAG_CONTAINER_INPUT: ClassVar[str] = 'container-input'
FLAG_COUNTY: ClassVar[str] = Base.FLAG_COUNTY
FLAG_CSRF_TOKEN: ClassVar[str] = 'X-CSRFToken'
FLAG_CURRENCY: ClassVar[str] = 'currency'
FLAG_DATA: ClassVar[str] = 'data'
FLAG_DATE_FROM: ClassVar[str] = Base.FLAG_DATE_FROM
FLAG_DATE_TO: ClassVar[str] = Base.FLAG_DATE_TO
FLAG_DELETE: ClassVar[str] = 'delete'
FLAG_DESCRIPTION: ClassVar[str] = Base.FLAG_DESCRIPTION
FLAG_DETAIL: ClassVar[str] = 'detail'
FLAG_DIALOG: ClassVar[str] = 'dialog' # try <dialog> element
FLAG_DIALOG: ClassVar[str] = 'dialog'
FLAG_DIRTY: ClassVar[str] = 'dirty'
FLAG_DISPLAY_ORDER: ClassVar[str] = Base.FLAG_DISPLAY_ORDER
FLAG_EDIT: ClassVar[str] = 'edit'
@@ -92,47 +90,25 @@ class Model_View_Base(BaseModel, ABC):
FLAG_ERROR: ClassVar[str] = 'error'
FLAG_EXPANDED: ClassVar[str] = 'expanded'
FLAG_FAILURE: ClassVar[str] = 'failure'
FLAG_FAX: ClassVar[str] = Base.FLAG_FAX
FLAG_FILTER: ClassVar[str] = 'filter'
FLAG_FORM: ClassVar[str] = 'form'
FLAG_FORM_FILTERS: ClassVar[str] = 'form-filters'
FLAG_HAMBURGER: ClassVar[str] = 'hamburger'
FLAG_IMAGE_LOGO: ClassVar[str] = 'image-logo'
FLAG_INITIALISED: ClassVar[str] = 'initialised'
FLAG_IS_INCLUDED_VAT: ClassVar[str] = 'is_included_VAT'
FLAG_LEFT_HAND_STUB: ClassVar[str] = 'lhs'
FLAG_LOGO: ClassVar[str] = 'logo'
FLAG_MESSAGE: ClassVar[str] = 'message'
FLAG_MESSAGE: ClassVar[str] = Contact_Form.FLAG_MESSAGE
FLAG_MODAL: ClassVar[str] = 'modal'
FLAG_NAME: ClassVar[str] = Base.FLAG_NAME
FLAG_NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME_ATTR_OPTION_TEXT
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_ADMIN_STORE_STRIPE_PRICES: ClassVar[str] = 'navAdminStoreStripePrices'
FLAG_NAV_ADMIN_STORE_STRIPE_PRODUCTS: ClassVar[str] = 'navAdminStoreStripeProducts'
FLAG_NAV_CONTACT: ClassVar[str] = 'navContact'
FLAG_NAV_HOME: ClassVar[str] = 'navHome'
FLAG_NAV_SERVICES: ClassVar[str] = 'navServices'
FLAG_NAV_STORE_HOME: ClassVar[str] = 'navStoreHome'
FLAG_NAV_STORE_MANUFACTURING_PURCHASE_ORDERS: ClassVar[str] = 'navStoreManufacturingPurchaseOrders'
FLAG_NAV_STORE_PRODUCTS: ClassVar[str] = 'navStoreProducts'
FLAG_NAV_STORE_PRODUCT_CATEGORIES: ClassVar[str] = 'navStoreProductCategories'
FLAG_NAV_STORE_PRODUCT_PERMUTATIONS: ClassVar[str] = 'navStoreProductPermutations'
FLAG_NAV_STORE_PRODUCT_PRICES: ClassVar[str] = 'navStoreProductPrices'
FLAG_NAV_STORE_PRODUCT_VARIATIONS: ClassVar[str] = 'navStoreProductVariations'
FLAG_NAV_STORE_STOCK_ITEMS: ClassVar[str] = 'navStoreStockItems'
FLAG_NAV_STORE_SUPPLIERS: ClassVar[str] = 'navStoreSuppliers'
FLAG_NAV_STORE_SUPPLIER_PURCHASE_ORDERS: ClassVar[str] = 'navStoreSupplierPurchaseOrders'
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_PHONE_NUMBER: ClassVar[str] = Base.FLAG_PHONE_NUMBER
FLAG_POSTCODE: ClassVar[str] = Base.FLAG_POSTCODE
FLAG_RIGHT_HAND_SIDE: ClassVar[str] = 'rhs'
FLAG_ROW: ClassVar[str] = 'row'
FLAG_ROW_NEW: ClassVar[str] = 'row-new'
@@ -142,28 +118,20 @@ class Model_View_Base(BaseModel, ABC):
FLAG_SLIDER: ClassVar[str] = 'slider'
FLAG_STATUS: ClassVar[str] = 'status'
FLAG_SUBMIT: ClassVar[str] = 'submit'
FLAG_SUBMITTED: ClassVar[str] = 'submitted'
FLAG_SUCCESS: ClassVar[str] = 'success'
FLAG_TEMPORARY_ELEMENT: ClassVar[str] = 'temporary-element'
FLAG_USER: ClassVar[str] = User.FLAG_USER
FLAG_WEBSITE: ClassVar[str] = Base.FLAG_WEBSITE
# flagIsDatePicker: ClassVar[str] = 'is-date-picker'
HASH_APPLY_FILTERS_STORE_PRODUCT_PERMUTATION: ClassVar[str] = '/store/permutation_filter'
HASH_CALLBACK_LOGIN: ClassVar[str] = '/callback-login'
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'
HASH_PAGE_ERROR_NO_PERMISSION: ClassVar[str] = '/error'
HASH_PAGE_HOME: ClassVar[str] = '/'
HASH_PAGE_LICENSE: ClassVar[str] = '/license'
HASH_PAGE_PRIVACY_POLICY: ClassVar[str] = '/privacy-policy'
HASH_PAGE_SERVICES: ClassVar[str] = '/services'
HASH_PAGE_USER_ACCOUNT: ClassVar[str] = '/user'
HASH_PAGE_USER_ADMIN: ClassVar[str] = '/user/admin'
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'
@@ -171,24 +139,8 @@ class Model_View_Base(BaseModel, ABC):
ID_BUTTON_SAVE: ClassVar[str] = 'buttonSave'
ID_CSRF_TOKEN: ClassVar[str] = 'X-CSRFToken'
ID_FORM_CONTACT: ClassVar[str] = 'formContact'
ID_FORM_CURRENCY: ClassVar[str] = 'formCurrency'
ID_FORM_DELIVERY_REGION: ClassVar[str] = 'formDeliveryRegion'
ID_FORM_FILTERS: ClassVar[str] = 'formFilters'
ID_FORM_IS_INCLUDED_VAT: ClassVar[str] = 'formIsIncludedVAT'
ID_LABEL_ERROR: ClassVar[str] = 'labelError'
"""
ID_MODAL_SERVICES: ClassVar[str] = 'modalServices'
ID_MODAL_TECHNOLOGIES: ClassVar[str] = 'modalTechnologies'
ID_BUTTON_NAV_ADMIN_HOME: ClassVar[str] = 'navAdminHome'
ID_BUTTON_NAV_ADMIN_STORE_STRIPE_PRICE: ClassVar[str] = 'navAdminStoreStripePrice'
ID_BUTTON_NAV_ADMIN_STORE_STRIPE_PRODUCT: ClassVar[str] = 'navAdminStoreStripeProduct'
# ID_BUTTON_NAV_CONTACT: ClassVar[str] = 'navContact'
ID_BUTTON_NAV_HOME: ClassVar[str] = 'navHome'
ID_BUTTON_NAV_SERVICES: ClassVar[str] = 'navServices'
ID_BUTTON_NAV_USER_ADMIN: ClassVar[str] = 'navUserAdmin'
ID_BUTTON_NAV_USER_LOGIN: ClassVar[str] = 'navUserLogin'
ID_BUTTON_NAV_USER_LOGOUT: ClassVar[str] = 'navUserLogout'
"""
ID_OVERLAY_CONFIRM: ClassVar[str] = 'overlayConfirm'
ID_OVERLAY_ERROR: ClassVar[str] = 'overlayError'
ID_OVERLAY_HAMBURGER: ClassVar[str] = 'overlayHamburger'
@@ -198,23 +150,10 @@ class Model_View_Base(BaseModel, ABC):
NAME_COMPANY: ClassVar[str] = 'Precision And Research Technology Systems Limited'
NAME_COMPANY_SHORT: ClassVar[str] = 'PARTS Ltd'
NAME_CSRF_TOKEN: ClassVar[str] = 'csrf-token'
# URL_HOST: ClassVar[str] = os.env() 'http://127.0.0.1:5000' # 'https://www.partsltd.co.uk'
URL_GITHUB: ClassVar[str] = 'https://github.com/Teddy-1024'
URL_LINKEDIN: ClassVar[str] = 'https://uk.linkedin.com/in/lordteddyms'
URL_LINKEDIN: ClassVar[str] = 'https://uk.linkedin.com/in/teddyms'
# Attributes
"""
is_user_logged_in: bool
id_user: str
form_is_included_VAT: Form_Is_Included_VAT
form_delivery_region: Form_Delivery_Region
form_currency: Form_Currency
# app: Flask
db: SQLAlchemy
"""
# """
hash_page_current: str
# """
app: Flask = None
session: None = None
is_page_store: bool = None
@@ -229,48 +168,18 @@ class Model_View_Base(BaseModel, ABC):
def title(self):
pass
"""
def __new__(cls, db, info_user, app): # , *args, **kwargs
# Initialiser - validation
_m = 'Model_View_Base.__new__'
v_arg_type = 'class attribute'
Helper_App.console_log(f'{_m}\nstarting')
# return super().__new__(cls, *args, **kwargs)
av.val_instance(db, 'db', _m, SQLAlchemy, v_arg_type=v_arg_type)
return super(Model_View_Base, cls).__new__(cls)
"""
def __init__(self, hash_page_current, **kwargs):
# Constructor
"""
_m = 'Model_View_Base.__init__'
v_arg_type = 'class attribute'
Helper_App.console_log(f'{_m}\nstarting')
av.val_instance(db, 'db', _m, SQLAlchemy, v_arg_type=v_arg_type)
"""
BaseModel.__init__(self, hash_page_current=hash_page_current, **kwargs)
"""
self.db = db
self.session = session
info_user = self.get_info_user()
Helper_App.console_log(f'info_user: {info_user}\ntype: {str(type(info_user))}')
self.is_user_logged_in = ('sub' in list(info_user.keys()) and not info_user['sub'] == '' and not str(type(info_user['sub'])) == "<class 'NoneType'?")
Helper_App.console_log(f'is_user_logged_in: {self.is_user_logged_in}')
self.id_user = info_user['sub'] if self.is_user_logged_in else ''
self.app = app
"""
self.app = current_app
with self.app.app_context():
self.session = session
# self.form_is_included_VAT = Form_Is_Included_VAT()
# self.form_delivery_region = Form_Delivery_Region()
# self.form_currency = Form_Currency()
self.is_page_store = False
Helper_App.console_log(f'session: {self.session}')
datastore_user = DataStore_User()
self.user = datastore_user.get_user_session()
self.is_user_logged_in = self.user.is_logged_in
Helper_App.console_log(f'model_view_base init end - model.user: {self.user}')
datastore_base = DataStore_Base()
self.user = datastore_base.get_user_session()
self.is_user_logged_in = self.user.get_is_logged_in()
# Helper_App.console_log(f'model_view_base init end - model.user: {self.user}')
def output_bool(self, boolean):
return str(boolean).lower()
@@ -281,34 +190,6 @@ class Model_View_Base(BaseModel, ABC):
def get_user_session(self):
datastore_user = DataStore_User()
return datastore_user.get_user_session()
"""
def get_is_admin_store_user(self):
datastore_store = DataStore_Store()
user = datastore_store.get_user_session()
if not user.is_logged_in: return False
filters_user = Parameters_User.from_user(user) # get_default(datastore_store)
users, errors = datastore_store.get_many_user(filters_user)
try:
user = users[0]
return av.input_bool(user.can_admin_store, 'can_admin_store', 'Model_View_Base.get_is_admin_store_user')
except:
return False
user = self.get_user_session()
return user.can_admin_store
def get_is_admin_user_user(self):
datastore_store = DataStore_Store()
user = datastore_store.get_user_session()
if not user.is_logged_in: return False
filters_user = Parameters_User.from_user(user) # .get_default(datastore_store)
users, errors = datastore_store.get_many_user(filters_user)
try:
user = users[0]
return av.input_bool(user.can_admin_user, 'can_admin_user', 'Model_View_Base.get_is_admin_user_user')
except:
return False
"""
def get_many_access_level(self, filters=None):
_m = 'Model_View_Store.get_many_access_level'
@@ -355,7 +236,6 @@ class Model_View_Base(BaseModel, ABC):
if preview_str != '':
preview_str += '\n'
obj_json = obj.to_json()
Helper_App.console_log(f'obj_json: {obj_json}')
preview_str += obj_json[obj_json[Base.FLAG_NAME_ATTR_OPTION_TEXT]]
return preview_str
@staticmethod

View File

@@ -11,6 +11,7 @@ Data model for contact view
"""
# internal
from business_objects.project_hub.contact_form import Contact_Form
from models.model_view_base import Model_View_Base
# from routes import bp_home
from lib import argument_validation as av
@@ -22,18 +23,6 @@ from pydantic import BaseModel
from typing import ClassVar
class Model_View_Contact(Model_View_Base):
# Attributes
FLAG_COMPANY_NAME: ClassVar[str] = 'company_name'
FLAG_CONTACT_NAME: ClassVar[str] = 'contact_name'
FLAG_RECEIVE_MARKETING: ClassVar[str] = 'receive_marketing'
"""
ID_EMAIL: ClassVar[str] = 'email'
ID_COMPANY_NAME: ClassVar[str] = 'company_name'
ID_CONTACT_NAME: ClassVar[str] = 'contact_name'
ID_MESSAGE: ClassVar[str] = 'msg'
ID_RECEIVE_MARKETING: ClassVar[str] = 'receive_marketing'
ID_NAME: ClassVar[str] = 'name'
"""
form_contact: Form_Contact

View File

@@ -0,0 +1,31 @@
"""
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

@@ -1,40 +0,0 @@
"""
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'
# Attributes
currencies: list = None
regions: list = None
users: list = None
@property
def title(self):
return 'User'
def __init__(self, hash_page_current=Model_View_Base.HASH_PAGE_USER_ACCOUNT):
# Constructor
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()

BIN
packages-microsoft-prod.deb Normal file

Binary file not shown.

View File

@@ -1,182 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: App General
Feature: App
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
# VARIABLE INSTANTIATION
# METHODS
# IMPORTS
import os
import stripe
import json
from flask import Flask, render_template, render_template_string, jsonify, request, send_from_directory, redirect
from dotenv import load_dotenv, find_dotenv
from config import app_config
# VARIABLE INSTANTIATION
key_secret = os.environ.get("KEY_SECRET_STRIPE")
key_public = os.environ.get("KEY_PUBLIC_STRIPE") # 'pk_test_51OGrxlL7BuLKjoMpfpfw7bSmZZK1MhqMoQ5VhW2jUj7YtoEejO4vqnxKPiqTHHuh9U4qqkywbPCSI9TpFKtr4SYH007KHMWs68'
# METHODS
def create_product_price():
print(f'stripe.api_key = {stripe.api_key}')
starter_subscription = stripe.Product.create(
name="Starter Subscription",
description="$12/Month subscription",
)
starter_subscription_price = stripe.Price.create(
unit_amount=1200,
currency="usd",
recurring={"interval": "month"},
product=starter_subscription['id'],
)
# Save these identifiers
print(f"Success! Here is your starter subscription product id: {starter_subscription.id}")
print(f"Success! Here is your starter subscription price id: {starter_subscription_price.id}")
return starter_subscription_price.id
def get_file_str(f_address):
f = open(f_address)
return f.read()
# Ensure environment variables are set.
price = os.getenv('PRICE')
if price is None or price == 'price_12345' or price == '':
print('You must set a Price ID in .env. Please see the README.')
exit(0)
# For sample support and debugging, not required for production:
stripe.set_app_info(
'stripe-samples/checkout-one-time-payments',
version='0.0.1',
url='https://github.com/stripe-samples/checkout-one-time-payments')
# stripe.api_version = '2020-08-27'
stripe.api_key = key_secret # os.getenv('KEY_SECRET_STRIPE')
# app_dir = str(os.path.abspath(os.path.join(
# __file__, "..", "..")))
# static_dir = str(os.path.abspath(os.path.join(
# app_dir, os.getenv("STATIC_DIR"))))
# template_dir = str(os.path.abspath(os.path.join(
# app_dir, os.getenv("TEMPLATE_DIR"))))
app = Flask(__name__) # , static_folder=static_dir,
# static_url_path="", template_folder=template_dir)
app.config.from_object(app_config)
@app.route('/', methods=['GET'])
def home():
# return render_template(f'{app_dir}\\templates\\_home.html') # f'{app_dir}\\templates\\layout.html')
# return render_template_string(get_file_str(f'{app_dir}\\templates\\_home.html')) # f'{app_dir}\\templates\\layout.html')
return render_template('_home.html', title='Home')
@app.route('/store', methods=['GET'])
def store_home():
return render_template('_store_home.html', title='Store Home')
@app.route('/contact')
def contact():
return render_template('_contact.html', title='Contact Us')
@app.route('/config', methods=['GET'])
def get_publishable_key():
price = stripe.Price.retrieve(os.getenv('PRICE'))
return jsonify({
'publicKey': key_public, # os.getenv('KEY_PUBLIC_STRIPE'),
'unitAmount': price['unit_amount'],
'currency': price['currency']
})
# Fetch the Checkout Session to display the JSON result on the success page
@app.route('/checkout-session', methods=['GET'])
def get_checkout_session():
id = request.args.get('sessionId')
print(f'checkout session id: {id}')
checkout_session = stripe.checkout.Session.retrieve(id)
return jsonify(checkout_session)
@app.route('/create-checkout-session', methods=['POST'])
def create_checkout_session():
quantity = request.form.get('quantity', 1)
domain_url = os.getenv('DOMAIN')
try:
# Create new Checkout Session for the order
# Other optional params include:
# [billing_address_collection] - to display billing address details on the page
# [customer] - if you have an existing Stripe Customer ID
# [payment_intent_data] - lets capture the payment later
# [customer_email] - lets you prefill the email input in the form
# [automatic_tax] - to automatically calculate sales tax, VAT and GST in the checkout page
# For full details see https://stripe.com/docs/api/checkout/sessions/create
# ?session_id={CHECKOUT_SESSION_ID} means the redirect will have the session ID set as a query param
checkout_session = stripe.checkout.Session.create(
success_url=domain_url + '/success.html?session_id={CHECKOUT_SESSION_ID}',
cancel_url=domain_url + '/canceled.html',
mode='subscription', # 'payment',
# automatic_tax={'enabled': True},
line_items=[{
'price': os.getenv('PRICE'),
'quantity': quantity,
}]
)
return redirect(checkout_session.url, code=303)
except Exception as e:
return jsonify(error=str(e)), 403
@app.route('/webhook', methods=['POST'])
def webhook_received():
# You can use webhooks to receive information about asynchronous payment events.
# For more about our webhook events check out https://stripe.com/docs/webhooks.
webhook_secret = os.getenv('STRIPE_WEBHOOK_SECRET')
request_data = json.loads(request.data)
if webhook_secret:
# Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
signature = request.headers.get('stripe-signature')
try:
event = stripe.Webhook.construct_event(
payload=request.data, sig_header=signature, secret=webhook_secret)
data = event['data']
except Exception as e:
return e
# Get the type of webhook event sent - used to check the status of PaymentIntents.
event_type = event['type']
else:
data = request_data['data']
event_type = request_data['type']
data_object = data['object']
print('event ' + event_type)
if event_type == 'checkout.session.completed':
print('🔔 Payment succeeded!')
return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS})
if __name__ == '__main__':
# stripe.api_key = key_secret
# create_product_price()
# Setup Stripe python client library.
load_dotenv(find_dotenv())
app.run(port=4242, debug=True)

View File

@@ -14,3 +14,5 @@ authlib
pydantic
# psycopg2
requests
cryptography
altcha

File diff suppressed because it is too large Load Diff

View File

@@ -1,337 +1,71 @@
/* Clear Store DataBase */
USE partsltd_prod;
-- Permanent Temp Tables
DROP TABLE IF EXISTS partsltd_prod.tmp_ph_Calc_User;
DROP TABLE IF EXISTS partsltd_prod.tmp_core_Msg_Error;
DROP TABLE IF EXISTS partsltd_prod.tmp_ph_User;
DROP TABLE IF EXISTS partsltd_prod.tmp_ph_User_Role_Link;
-- Drop dependencies
DROP TABLE IF EXISTS tmp_Shop_Calc_User;
DROP TABLE IF EXISTS tmp_Product_Calc_User;
DROP TABLE IF EXISTS tmp_Product_p_Shop_User_Eval;
DROP TABLE IF EXISTS tmp_Msg_Error;
DROP TABLE IF EXISTS tmp_Currency;
DROP TABLE IF EXISTS tmp_Delivery_Option;
DROP TABLE IF EXISTS tmp_Delivery_Region;
DROP TABLE IF EXISTS tmp_Region;
DROP TABLE IF EXISTS tmp_Price;
DROP TABLE IF EXISTS tmp_Shop_User;
DROP TABLE IF EXISTS tmp_Shop_Order;
DROP TABLE IF EXISTS tmp_Shop_Product;
DROP TABLE IF EXISTS tmp_Product;
DROP TABLE IF EXISTS tmp_Product_Permutation;
DROP TABLE IF EXISTS tmp_Permutation_Variation_Link;
DROP TABLE IF EXISTS tmp_Permutation;
DROP TABLE IF EXISTS tmp_Shop_Product_p_shop_calc_user;
DROP TABLE IF EXISTS tmp_Shop_Product_p_Shop_Calc_User;
DROP TABLE IF EXISTS tmp_Shop_Image;
DROP TABLE IF EXISTS tmp_Image;
DROP TABLE IF EXISTS tmp_Product_Image;
DROP TABLE IF EXISTS tmp_Shop_Variation;
DROP TABLE IF EXISTS tmp_Variation;
DROP TABLE IF EXISTS tmp_Variation_Type;
DROP TABLE IF EXISTS tmp_Shop_Discount;
DROP TABLE IF EXISTS tmp_Discount;
DROP TABLE IF EXISTS tmp_Shop_Category;
DROP TABLE IF EXISTS tmp_Category;
DROP TABLE IF EXISTS tmp_Shop_Product_Category;
DROP TABLE IF EXISTS tmp_Product_Category;
DROP TABLE IF EXISTS tmp_Shop_Product_Currency_Region_Link;
DROP TABLE IF EXISTS tmp_Shop_Product_Currency_Link;
DROP TABLE IF EXISTS tmp_User_Role_Link;
DROP TABLE IF EXISTS tmp_Shop_Basket;
DROP TABLE IF EXISTS tmp_Shop_Supplier_Purchase_Order_Product_Link;
DROP TABLE IF EXISTS tmp_Supplier_Purchase_Order_Product_Link;
DROP TABLE IF EXISTS tmp_Shop_Supplier_Purchase_Order;
DROP TABLE IF EXISTS tmp_Supplier_Purchase_Order;
DROP TABLE IF EXISTS tmp_Shop_Supplier;
DROP TABLE IF EXISTS tmp_Supplier;
DROP TABLE IF EXISTS tmp_Supplier_Address;
DROP TABLE IF EXISTS tmp_Shop_Manufacturing_Purchase_Order_Product_Link;
DROP TABLE IF EXISTS tmp_Manufacturing_Purchase_Order_Product_Link;
DROP TABLE IF EXISTS tmp_Shop_Manufacturing_Purchase_Order;
DROP TABLE IF EXISTS tmp_Manufacturing_Purchase_Order;
DROP TABLE IF EXISTS tmp_Shop_Customer;
DROP TABLE IF EXISTS tmp_Shop_Customer_Sale_Order_Product_Link;
DROP TABLE IF EXISTS tmp_Shop_Customer_Sale_Order;
DROP TABLE IF EXISTS tmp_Get_Variation_From_Csv_Variations;
-- Permanent Tables
DROP TABLE IF EXISTS partsltd_prod.PH_Contact_Form_Temp;
DROP TABLE IF EXISTS partsltd_prod.PH_Contact_Form_Audit;
DROP TABLE IF EXISTS partsltd_prod.PH_Contact_Form;
DROP TABLE IF EXISTS partsltd_prod.PH_Contact_Form_Change_Set;
-- Delete old tables
DROP TABLE IF EXISTS Split_Temp;
DROP TABLE IF EXISTS Split_Key_Value_Pair_Csv_Temp;
DROP TABLE IF EXISTS Split_Key_Value_Pair_Temp;
DROP TABLE IF EXISTS partsltd_prod.PH_Calc_User_Temp;
DROP TABLE IF EXISTS Shop_User_Eval_Temp;
DROP TABLE IF EXISTS Shop_Calc_User_Temp;
DROP TABLE IF EXISTS partsltd_prod.PH_User_Role_Link_Audit;
DROP TABLE IF EXISTS partsltd_prod.PH_User_Role_Link;
DROP TABLE IF EXISTS Shop_Customer_Sales_Order_Product_Link_Temp;
DROP TABLE IF EXISTS Shop_Customer_Sales_Order_Product_Link_Audit;
DROP TABLE IF EXISTS Shop_Customer_Sales_Order_Product_Link;
DROP TABLE IF EXISTS partsltd_prod.PH_Role_Permission_Link_Audit;
DROP TABLE IF EXISTS partsltd_prod.PH_Role_Permission_Link;
DROP TABLE IF EXISTS Shop_Manufacturing_Purchase_Order_Product_Link_Temp;
DROP TABLE IF EXISTS Shop_Manufacturing_Purchase_Order_Product_Link_Audit;
DROP TABLE IF EXISTS Shop_Manufacturing_Purchase_Order_Product_Link;
DROP TABLE IF EXISTS partsltd_prod.PH_Role_Audit;
DROP TABLE IF EXISTS partsltd_prod.PH_Role;
DROP TABLE IF EXISTS Shop_Supplier_Purchase_Order_Product_Link_Temp;
DROP TABLE IF EXISTS Shop_Supplier_Purchase_Order_Product_Link_Audit;
DROP TABLE IF EXISTS Shop_Supplier_Purchase_Order_Product_Link;
DROP TABLE IF EXISTS partsltd_prod.PH_User_Temp;
DROP TABLE IF EXISTS partsltd_prod.PH_User_Audit;
DROP TABLE IF EXISTS partsltd_prod.PH_User;
DROP TABLE IF EXISTS Shop_Stock_Item_Temp;
DROP TABLE IF EXISTS Shop_Stock_Item_Audit;
DROP TABLE IF EXISTS Shop_Stock_Item;
DROP TABLE IF EXISTS partsltd_prod.PH_Permission_Audit;
DROP TABLE IF EXISTS partsltd_prod.PH_Permission;
DROP TABLE IF EXISTS Shop_Customer_Sales_Order_Audit;
DROP TABLE IF EXISTS Shop_Customer_Sales_Order;
DROP TABLE IF EXISTS partsltd_prod.PH_Permission_Group_Audit;
DROP TABLE IF EXISTS partsltd_prod.PH_Permission_Group;
DROP TABLE IF EXISTS Shop_Customer_Temp;
DROP TABLE IF EXISTS Shop_Customer_Audit;
DROP TABLE IF EXISTS Shop_Customer;
DROP TABLE IF EXISTS partsltd_prod.PH_Access_Level_Audit;
DROP TABLE IF EXISTS partsltd_prod.PH_Access_Level;
DROP TABLE IF EXISTS Shop_Manufacturing_Purchase_Order_Temp;
DROP TABLE IF EXISTS Shop_Manufacturing_Purchase_Order_Audit;
DROP TABLE IF EXISTS Shop_Manufacturing_Purchase_Order;
DROP TABLE IF EXISTS partsltd_prod.PH_User_Change_Set;
DROP TABLE IF EXISTS Shop_Supplier_Purchase_Order_Temp;
DROP TABLE IF EXISTS Shop_Supplier_Purchase_Order_Audit;
DROP TABLE IF EXISTS Shop_Supplier_Purchase_Order;
DROP TABLE IF EXISTS partsltd_prod.CORE_Split_Key_Value_Pair_Csv_Temp;
DROP TABLE IF EXISTS partsltd_prod.CORE_Split_Temp;
DROP TABLE IF EXISTS Shop_Supplier_Address_Temp;
DROP TABLE IF EXISTS Shop_Supplier_Address_Audit;
DROP TABLE IF EXISTS Shop_Supplier_Address;
DROP TABLE IF EXISTS partsltd_prod.CORE_Msg_Error_Type;
DROP TABLE IF EXISTS Shop_Supplier_Temp;
DROP TABLE IF EXISTS Shop_Supplier_Audit;
DROP TABLE IF EXISTS Shop_Supplier;
-- Stored Procedures
DROP PROCEDURE IF EXISTS partsltd_prod.p_ph_test_get_many_contact_form;
DROP PROCEDURE IF EXISTS partsltd_prod.p_ph_get_many_contact_form;
DROP PROCEDURE IF EXISTS partsltd_prod.p_ph_test_save_contact_form;
DROP PROCEDURE IF EXISTS partsltd_prod.p_ph_save_contact_form;
DROP TABLE IF EXISTS Shop_User_Order_Product_Link_Audit;
DROP TABLE IF EXISTS Shop_User_Order_Product_Link;
DROP PROCEDURE IF EXISTS partsltd_prod.p_ph_clear_calc_user;
DROP PROCEDURE IF EXISTS partsltd_prod.p_ph_calc_user;
DROP TABLE IF EXISTS Shop_User_Order_Audit;
DROP TABLE IF EXISTS Shop_User_Order;
DROP PROCEDURE IF EXISTS partsltd_prod.p_core_clear_split_key_value_pair_csv;
DROP PROCEDURE IF EXISTS partsltd_prod.p_core_split_key_value_pair_csv;
DROP PROCEDURE IF EXISTS partsltd_prod.p_core_clear_split;
DROP PROCEDURE IF EXISTS partsltd_prod.p_core_split;
DROP PROCEDURE IF EXISTS partsltd_prod.p_clear_split_key_value_pair_csv;
DROP PROCEDURE IF EXISTS partsltd_prod.p_split_key_value_pair_csv;
DROP PROCEDURE IF EXISTS partsltd_prod.p_clear_split;
DROP PROCEDURE IF EXISTS partsltd_prod.p_split;
DROP TABLE IF EXISTS Shop_User_Order_Status_Audit;
DROP TABLE IF EXISTS Shop_User_Order_Status;
DROP TABLE IF EXISTS Shop_User_Basket_Audit;
DROP TABLE IF EXISTS Shop_User_Basket;
DROP TABLE IF EXISTS Shop_User_Address_Audit;
DROP TABLE IF EXISTS Shop_User_Address;
DROP TABLE IF EXISTS Shop_User_Role_Link_Audit;
DROP TABLE IF EXISTS Shop_User_Role_Link;
DROP TABLE IF EXISTS Shop_User_Temp;
DROP TABLE IF EXISTS Shop_User_Audit;
DROP TABLE IF EXISTS Shop_User;
DROP TABLE IF EXISTS Shop_Role_Permission_Link_Audit;
DROP TABLE IF EXISTS Shop_Role_Permission_Link;
DROP TABLE IF EXISTS Shop_Role_Audit;
DROP TABLE IF EXISTS Shop_Role;
DROP TABLE IF EXISTS Shop_Permission_Audit;
DROP TABLE IF EXISTS Shop_Permission;
DROP TABLE IF EXISTS Shop_Permission_Group_Audit;
DROP TABLE IF EXISTS Shop_Permission_Group;
DROP TABLE IF EXISTS Shop_Discount_Region_Currency_Link_Audit;
DROP TABLE IF EXISTS Shop_Discount_Region_Currency_Link;
DROP TABLE IF EXISTS Shop_Discount_Audit;
DROP TABLE IF EXISTS Shop_Discount;
DROP TABLE IF EXISTS Shop_Product_Permutation_Delivery_Option_Link_Audit;
DROP TABLE IF EXISTS Shop_Product_Permutation_Delivery_Option_Link;
DROP TABLE IF EXISTS Shop_Product_Delivery_Option_Link_Audit;
DROP TABLE IF EXISTS Shop_Product_Delivery_Option_Link;
DROP TABLE IF EXISTS Shop_Delivery_Option_Audit;
DROP TABLE IF EXISTS Shop_Delivery_Option;
DROP TABLE IF EXISTS Shop_Product_Image_Audit;
DROP TABLE IF EXISTS Shop_Product_Image;
DROP TABLE IF EXISTS Shop_Image_Audit;
DROP TABLE IF EXISTS Shop_Image;
DROP TABLE IF EXISTS Shop_Product_Price_Temp;
DROP TABLE IF EXISTS Shop_Product_Price_Audit;
DROP TABLE IF EXISTS Shop_Product_Price;
DROP TABLE IF EXISTS Shop_Product_Currency_Region_Link_Audit;
DROP TABLE IF EXISTS Shop_Product_Currency_Region_Link;
DROP TABLE IF EXISTS Shop_Product_Currency_Link_Audit;
DROP TABLE IF EXISTS Shop_Product_Currency_Link;
DROP TABLE IF EXISTS Shop_Product_Variation_Link_Audit;
DROP TABLE IF EXISTS Shop_Product_Variation_Link;
DROP TABLE IF EXISTS Shop_Product_Permutation_Variation_Link_Temp;
DROP TABLE IF EXISTS Shop_Product_Permutation_Variation_Link_Audit;
DROP TABLE IF EXISTS Shop_Product_Permutation_Variation_Link;
DROP TABLE IF EXISTS Shop_Variation_Temp;
DROP TABLE IF EXISTS Shop_Variation_Audit;
DROP TABLE IF EXISTS Shop_Variation;
DROP TABLE IF EXISTS Shop_Product_Variation_Type_Link_Audit;
DROP TABLE IF EXISTS Shop_Product_Variation_Type_Link;
DROP TABLE IF EXISTS Shop_Product_Variation_Temp;
DROP TABLE IF EXISTS Shop_Product_Variation;
DROP TABLE IF EXISTS Shop_Variation_Type_Temp;
DROP TABLE IF EXISTS Shop_Variation_Type_Audit;
DROP TABLE IF EXISTS Shop_Variation_Type;
DROP TABLE IF EXISTS Shop_Product_Variation_Type_Temp;
DROP TABLE IF EXISTS Shop_Product_Variation_Type;
DROP TABLE IF EXISTS Shop_Product_Permutation_Temp;
DROP TABLE IF EXISTS Shop_Product_Permutation_Audit;
DROP TABLE IF EXISTS Shop_Product_Permutation;
DROP TABLE IF EXISTS Shop_Interval_Recurrence_Audit;
DROP TABLE IF EXISTS Shop_Interval_Recurrence;
DROP TABLE IF EXISTS Shop_Product_Audit;
DROP TABLE IF EXISTS Shop_Product;
DROP TABLE IF EXISTS Shop_Product_Temp;
DROP TABLE IF EXISTS Shop_Product_Category_Temp;
DROP TABLE IF EXISTS Shop_Product_Category_Audit;
DROP TABLE IF EXISTS Shop_Product_Category;
DROP TABLE IF EXISTS Shop_Category_Audit;
DROP TABLE IF EXISTS Shop_Category;
DROP TABLE IF EXISTS Shop_Tax_Or_Surcharge_Temp;
DROP TABLE IF EXISTS Shop_Tax_Or_Surcharge_Audit;
DROP TABLE IF EXISTS Shop_Tax_Or_Surcharge;
DROP TABLE IF EXISTS Shop_Currency_Temp;
DROP TABLE IF EXISTS Shop_Currency_Audit;
DROP TABLE IF EXISTS Shop_Currency;
DROP TABLE IF EXISTS Shop_Storage_Location_Branch_Temp;
DROP TABLE IF EXISTS Shop_Storage_Location_Branch_Audit;
DROP TABLE IF EXISTS Shop_Storage_Location_Branch;
DROP TABLE IF EXISTS Shop_Storage_Location_Temp;
DROP TABLE IF EXISTS Shop_Storage_Location_Audit;
DROP TABLE IF EXISTS Shop_Storage_Location;
DROP TABLE IF EXISTS Shop_Plant_Temp;
DROP TABLE IF EXISTS Shop_Plant_Audit;
DROP TABLE IF EXISTS Shop_Plant;
DROP TABLE IF EXISTS Shop_Address_Audit;
DROP TABLE IF EXISTS Shop_Address;
DROP TABLE IF EXISTS Shop_Delivery_Region_Branch_Audit;
DROP TABLE IF EXISTS Shop_Delivery_Region_Branch;
DROP TABLE IF EXISTS Shop_Region_Branch_Temp;
DROP TABLE IF EXISTS Shop_Region_Branch_Audit;
DROP TABLE IF EXISTS Shop_Region_Branch;
DROP TABLE IF EXISTS Shop_Delivery_Region_Audit;
DROP TABLE IF EXISTS Shop_Delivery_Region;
DROP TABLE IF EXISTS Shop_Region_Temp;
DROP TABLE IF EXISTS Shop_Region_Audit;
DROP TABLE IF EXISTS Shop_Region;
DROP TABLE IF EXISTS Shop_Unit_Measurement_Conversion_Audit;
DROP TABLE IF EXISTS Shop_Unit_Measurement_Conversion;
DROP TABLE IF EXISTS Shop_Unit_Measurement_Audit;
DROP TABLE IF EXISTS Shop_Unit_Measurement;
DROP TABLE IF EXISTS Shop_Image_Type_Audit;
DROP TABLE IF EXISTS Shop_Image_Type;
DROP TABLE IF EXISTS Shop_General_Audit;
DROP TABLE IF EXISTS Shop_General;
DROP TABLE IF EXISTS File_Type_Audit;
DROP TABLE IF EXISTS File_Type;
DROP TABLE IF EXISTS Msg_Error_Type;
DROP TABLE IF EXISTS Shop_Msg_Error_Type;
DROP TABLE IF EXISTS Shop_Access_Level_Audit;
DROP TABLE IF EXISTS Shop_Access_Level;
DROP TABLE IF EXISTS Shop_Sales_And_Purchasing_Change_Set;
DROP TABLE IF EXISTS Shop_User_Change_Set;
DROP TABLE IF EXISTS Shop_Product_Change_Set;
-- Procedures
DROP PROCEDURE IF EXISTS p_split;
DROP PROCEDURE IF EXISTS p_clear_split_temp;
DROP PROCEDURE IF EXISTS p_split_key_value_pair_csv;
DROP PROCEDURE IF EXISTS p_clear_split_key_value_csv_temp;
DROP PROCEDURE IF EXISTS p_clear_split_key_value_pair_csv_temp;
DROP PROCEDURE IF EXISTS p_debug_timing_reporting;
DROP PROCEDURE IF EXISTS p_validate_guid;
DROP PROCEDURE IF EXISTS p_validate_guid_test;
DROP FUNCTION IF EXISTS fn_shop_get_product_permutation_name;
DROP PROCEDURE IF EXISTS p_shop_calc_user;
DROP PROCEDURE IF EXISTS p_shop_calc_user;
DROP PROCEDURE IF EXISTS p_shop_clear_user_eval_temp;
DROP PROCEDURE IF EXISTS p_shop_clear_calc_user;
DROP PROCEDURE IF EXISTS p_shop_get_many_access_level;
DROP PROCEDURE IF EXISTS p_shop_get_many_unit_measurement;
DROP PROCEDURE IF EXISTS p_shop_get_many_region;
DROP PROCEDURE IF EXISTS p_shop_get_many_plant;
DROP PROCEDURE IF EXISTS p_shop_get_many_storage_location;
DROP PROCEDURE IF EXISTS p_shop_get_many_currency;
DROP PROCEDURE IF EXISTS p_shop_save_category;
DROP PROCEDURE IF EXISTS p_shop_save_category_test;
DROP PROCEDURE IF EXISTS p_shop_save_product_category;
DROP PROCEDURE IF EXISTS p_shop_save_product_category_test;
DROP PROCEDURE IF EXISTS p_shop_save_product;
DROP PROCEDURE IF EXISTS p_shop_save_product_test;
DROP PROCEDURE IF EXISTS p_shop_calc_product_permutation;
DROP PROCEDURE IF EXISTS p_shop_clear_calc_product_permutation;
DROP PROCEDURE IF EXISTS p_shop_get_many_product;
DROP PROCEDURE IF EXISTS p_shop_get_many_stripe_product_new;
DROP PROCEDURE IF EXISTS p_shop_save_permutation;
DROP PROCEDURE IF EXISTS p_shop_save_product_permutation;
DROP PROCEDURE IF EXISTS p_shop_save_product_permutation_test;
DROP PROCEDURE IF EXISTS p_shop_save_product_variation;
DROP PROCEDURE IF EXISTS p_shop_save_product_variation_test;
DROP PROCEDURE IF EXISTS p_shop_get_many_product_variation;
DROP FUNCTION IF EXISTS fn_shop_get_id_product_permutation_from_variation_csv_list;
DROP FUNCTION IF EXISTS fn_shop_get_product_variations_from_id_csv_list;
DROP FUNCTION IF EXISTS fn_shop_get_product_permutation_variations_csv;
DROP PROCEDURE IF EXISTS p_shop_save_stock_item;
DROP PROCEDURE IF EXISTS p_shop_save_stock_item_test;
DROP PROCEDURE IF EXISTS p_shop_get_many_stock_item;
DROP PROCEDURE IF EXISTS p_shop_get_many_product_price_and_discount_and_delivery_option;
DROP PROCEDURE IF EXISTS p_shop_get_many_product_price_and_discount_and_delivery_option;
DROP PROCEDURE IF EXISTS p_shop_get_many_stripe_price_new;
DROP PROCEDURE IF EXISTS p_shop_save_user;
DROP PROCEDURE IF EXISTS p_shop_edit_user;
DROP PROCEDURE IF EXISTS p_shop_get_many_user;
DROP PROCEDURE IF EXISTS p_get_many_user;
DROP PROCEDURE IF EXISTS p_shop_get_many_user_basket;
DROP PROCEDURE IF EXISTS p_shop_edit_user_basket;
DROP PROCEDURE IF EXISTS p_shop_save_supplier;
DROP PROCEDURE IF EXISTS p_shop_save_supplier_test;
DROP PROCEDURE IF EXISTS p_shop_get_many_supplier;
DROP PROCEDURE IF EXISTS p_shop_save_supplier_purchase_order;
DROP PROCEDURE IF EXISTS p_shop_save_supplier_purchase_order_test;
DROP PROCEDURE IF EXISTS p_shop_get_many_supplier_purchase_order;
DROP PROCEDURE IF EXISTS p_shop_save_manufacturing_purchase_order;
DROP PROCEDURE IF EXISTS p_shop_save_manufacturing_purchase_order_test;
DROP PROCEDURE IF EXISTS p_shop_get_many_manufacturing_purchase_order;
DROP PROCEDURE IF EXISTS p_shop_save_customer;
DROP PROCEDURE IF EXISTS p_shop_get_many_customer;
DROP PROCEDURE IF EXISTS p_shop_save_customer_sales_order;
DROP PROCEDURE IF EXISTS p_shop_get_many_customer_sales_order;
DROP PROCEDURE IF EXISTS partsltd_prod.p_core_debug_timing_reporting;
DROP PROCEDURE IF EXISTS partsltd_prod.p_debug_timing_reporting;
DROP PROCEDURE IF EXISTS partsltd_prod.p_core_validate_guid;
DROP PROCEDURE IF EXISTS partsltd_prod.p_core_validate_guid_test;

View File

@@ -0,0 +1,16 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'CORE_Msg_Error_Type'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.CORE_Msg_Error_Type (
id_type INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, code VARCHAR(50) NOT NULL
, name VARCHAR(500) NOT NULL
, description VARCHAR(1000)
);

View File

@@ -1,13 +0,0 @@
-- Product Change Sets
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Change_Set';
CREATE TABLE Shop_Product_Change_Set (
id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
comment VARCHAR(500),
updated_last_on DATETIME,
updated_last_by VARCHAR(100)
);

View File

@@ -1,12 +0,0 @@
-- Split Staging
-- USE partsltd_prod;
-- DROP TABLE IF EXISTS Split_Temp;
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Split_Temp';
CREATE TABLE Split_Temp (
guid BINARY(36) NOT NULL
, display_order INT NOT NULL
, substring VARCHAR(4000) NOT NULL
);

View File

@@ -1,13 +0,0 @@
-- User Change Sets
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_User_Change_Set';
CREATE TABLE IF NOT EXISTS Shop_User_Change_Set (
id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
comment VARCHAR(500),
updated_last_on DATETIME,
updated_last_by VARCHAR(100)
);

View File

@@ -1,13 +0,0 @@
-- Split Key Value Pair CSV Staging
-- USE partsltd_prod;
-- DROP TABLE IF EXISTS Split_Temp;
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Split_Key_Value_Pair_Csv_Temp';
CREATE TABLE Split_Key_Value_Pair_Csv_Temp (
guid BINARY(36) NOT NULL
, id INT NOT NULL
, key_column VARCHAR(4000) NULL
, value_column VARCHAR(4000) NULL
);

View File

@@ -1,13 +0,0 @@
-- Sales And Purchasing Change Sets
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Sales_And_Purchasing_Change_Set';
CREATE TABLE Shop_Sales_And_Purchasing_Change_Set (
id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
comment VARCHAR(500),
updated_last_on DATETIME,
updated_last_by VARCHAR(100)
);

View File

@@ -1,23 +0,0 @@
-- Access Levels
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Access_Level';
CREATE TABLE IF NOT EXISTS Shop_Access_Level (
id_access_level INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50),
name VARCHAR(255),
priority INT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Access_Level_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_User_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Access Level Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Access_Level_Audit';
CREATE TABLE IF NOT EXISTS Shop_Access_Level_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_access_level INT NOT NULL,
CONSTRAINT FK_Shop_Access_Level_Audit_id_access_level
FOREIGN KEY (id_access_level)
REFERENCES Shop_Access_Level(id_access_level)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Access_Level_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_User_Change_Set(id_change_set)
);

View File

@@ -1,13 +0,0 @@
-- Error Message Type
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Msg_Error_Type';
CREATE TABLE IF NOT EXISTS Shop_Msg_Error_Type (
id_type INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(500) NOT NULL,
description VARCHAR(1000)
);

View File

@@ -1,17 +0,0 @@
-- File Types
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'File_Type';
CREATE TABLE IF NOT EXISTS File_Type (
id_type INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50),
name VARCHAR(100),
extension VARCHAR(50),
created_on DATETIME,
created_by INT,
updated_last_on DATETIME,
updated_last_by VARCHAR(100)
);

View File

@@ -1,22 +0,0 @@
-- File Type Audit
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'File_Type_Audit';
CREATE TABLE IF NOT EXISTS File_Type_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_type INT NOT NULL,
CONSTRAINT FK_File_Type_Audit_id_type
FOREIGN KEY (id_type)
REFERENCES File_Type(id_type)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
created_on DATETIME,
created_by INT,
updated_last_on DATETIME,
updated_last_by VARCHAR(100)
);

View File

@@ -1,17 +0,0 @@
-- Generic / shared properties
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_General';
CREATE TABLE IF NOT EXISTS Shop_General (
id_general INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
quantity_max FLOAT,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT CHK_Shop_General_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Shop General Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_General_Audit';
CREATE TABLE IF NOT EXISTS Shop_General_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_general INT NOT NULL,
CONSTRAINT FK_Shop_General_Audit_id_general
FOREIGN KEY (id_general)
REFERENCES Shop_General(id_general)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_General_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,27 +0,0 @@
-- Image Types
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Image_Type';
CREATE TABLE IF NOT EXISTS Shop_Image_Type (
id_type INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
/*
id_type_file INT NOT NULL,
CONSTRAINT FK_Shop_Image_Type_id_type_file
FOREIGN KEY (id_type_file)
REFERENCES File_Type(id_type),
*/
code VARCHAR(50),
name VARCHAR(255),
name_plural VARCHAR(256),
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Image_Type_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Image Type Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Image_Type_Audit';
CREATE TABLE IF NOT EXISTS Shop_Image_Type_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_type INT NOT NULL,
CONSTRAINT FK_Shop_Image_Type_Audit_id_type
FOREIGN KEY (id_type)
REFERENCES Shop_Image_Type(id_type)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Image_Type_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,15 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'CORE_Split_Temp'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.CORE_Split_Temp (
guid BINARY(36) NOT NULL
, display_order INT NOT NULL
, substring VARCHAR(4000) NOT NULL
);

View File

@@ -0,0 +1,16 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'CORE_Split_Key_Value_Pair_Csv_Temp'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.CORE_Split_Key_Value_Pair_Csv_Temp (
guid BINARY(36) NOT NULL
, id INT NOT NULL
, key_column VARCHAR(4000) NULL
, value_column VARCHAR(4000) NULL
);

View File

@@ -0,0 +1,16 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_User_Change_Set'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_User_Change_Set (
id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, comment VARCHAR(500)
, updated_last_on DATETIME
, id_user_updated_last_by INT
);

View File

@@ -1,18 +0,0 @@
-- Regions
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Region';
CREATE TABLE IF NOT EXISTS Shop_Region (
id_region INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(200) NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Region_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Region Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Region_Audit';
CREATE TABLE IF NOT EXISTS Shop_Region_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_region INT NOT NULL,
CONSTRAINT FK_Shop_Region_Audit_id_region
FOREIGN KEY (id_region)
REFERENCES Shop_Region(id_region)
ON UPDATE RESTRICT,
name_field VARCHAR(64) NOT NULL,
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Region_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,20 +0,0 @@
-- Region Temp
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Region_Temp';
CREATE TABLE IF NOT EXISTS Shop_Region_Temp (
id_region INT NOT NULL PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(200) NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Region_Temp_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,29 +0,0 @@
-- Region Branchs
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Region_Branch';
CREATE TABLE IF NOT EXISTS Shop_Region_Branch (
id_branch INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_region_parent INT NOT NULL,
CONSTRAINT FK_Shop_Region_Branch_id_region_parent
FOREIGN KEY (id_region_parent)
REFERENCES Shop_Region(id_region)
ON UPDATE RESTRICT,
id_region_child INT NOT NULL,
CONSTRAINT FK_Shop_Region_Branch_id_region_child
FOREIGN KEY (id_region_child)
REFERENCES Shop_Region(id_region)
ON UPDATE RESTRICT,
-- depth INT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Region_Branch_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,20 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Access_Level'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Access_Level (
id_access_level INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, code VARCHAR(50)
, name VARCHAR(255)
, priority INT NOT NULL
, display_order INT NOT NULL
, active BIT NOT NULL DEFAULT 1
);

View File

@@ -1,22 +0,0 @@
-- Region Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Region_Branch_Audit';
CREATE TABLE IF NOT EXISTS Shop_Region_Branch_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_branch INT NOT NULL,
CONSTRAINT FK_Shop_Region_Branch_Audit_id_branch
FOREIGN KEY (id_branch)
REFERENCES Shop_Region_Branch(id_branch)
ON UPDATE RESTRICT,
name_field VARCHAR(64) NOT NULL,
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Region_Branch_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,15 +0,0 @@
-- Region Branch Temp
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Region_Branch_Temp';
CREATE TABLE IF NOT EXISTS Shop_Region_Branch_Temp (
id_branch INT NOT NULL PRIMARY KEY,
id_region_parent INT NOT NULL,
id_region_child INT NOT NULL,
-- depth INT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL
);

View File

@@ -1,31 +0,0 @@
-- Addresses
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Address';
CREATE TABLE Shop_Address (
id_address INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_region INT NOT NULL
, CONSTRAINT FK_Shop_Address_id_region
FOREIGN KEY (id_region)
REFERENCES partsltd_prod.Shop_Region(id_region)
/*
, id_supplier INT NULL
, CONSTRAINT FK_Shop_Address_id_supplier
FOREIGN KEY (id_supplier)
REFERENCES partsltd_prod.Shop_Supplier(id_supplier)
*/
, postcode VARCHAR(20) NOT NULL
, address_line_1 VARCHAR(256) NOT NULL
, address_line_2 VARCHAR(256) NOT NULL
, city VARCHAR(256) NOT NULL
, county VARCHAR(256) NOT NULL
, active BIT NOT NULL DEFAULT 1
, created_on DATETIME
, created_by INT
, id_change_set INT
, CONSTRAINT FK_Shop_Address_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.Shop_User_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Plant
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Plant';
CREATE TABLE IF NOT EXISTS Shop_Plant (
id_plant INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(500) NOT NULL,
id_address INT NOT NULL,
CONSTRAINT FK_Shop_Plant_id_address
FOREIGN KEY (id_address)
REFERENCES Shop_Address(id_address),
id_user_manager INT NOT NULL,
active BIT NOT NULL DEFAULT 1,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Plant_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,21 +0,0 @@
-- Address Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Address_Audit';
CREATE TABLE IF NOT EXISTS Shop_Address_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_address INT NOT NULL,
CONSTRAINT FK_Shop_Address_Audit_id_address
FOREIGN KEY (id_address)
REFERENCES Shop_Address(id_address)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Address_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_User_Change_Set(id_change_set)
ON UPDATE RESTRICT
);

View File

@@ -1,22 +0,0 @@
-- Plant Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Plant_Audit';
CREATE TABLE IF NOT EXISTS Shop_Plant_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_plant INT NOT NULL,
CONSTRAINT FK_Shop_Plant_Audit_id_plant
FOREIGN KEY (id_plant)
REFERENCES Shop_Plant(id_plant)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Plant_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,17 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Permission_Group'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Permission_Group (
id_group INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, code VARCHAR(50)
, name VARCHAR(255)
, display_order INT NOT NULL
, active BIT NOT NULL DEFAULT 1
);

View File

@@ -1,16 +0,0 @@
-- Plant Temp
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Plant_Temp';
CREATE TABLE IF NOT EXISTS Shop_Plant_Temp (
id_plant INT NOT NULL PRIMARY KEY
, code VARCHAR(50) NOT NULL
, name VARCHAR(500) NOT NULL
, id_address INT NOT NULL
, id_user_manager INT NOT NULL
, active BIT NOT NULL DEFAULT 1
, guid BINARY(36) NOT NULL
);

View File

@@ -1,23 +0,0 @@
-- Storage Location
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Storage_Location';
CREATE TABLE IF NOT EXISTS Shop_Storage_Location (
id_location INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_plant INT NOT NULL,
CONSTRAINT FK_Shop_Storage_Location_id_plant
FOREIGN KEY (id_plant)
REFERENCES Shop_Plant(id_plant),
code VARCHAR(50) NOT NULL,
name VARCHAR(500) NOT NULL,
active BIT NOT NULL DEFAULT 1,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Storage_Location_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Storage Location Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Storage_Location_Audit';
CREATE TABLE IF NOT EXISTS Shop_Storage_Location_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_location INT NOT NULL,
CONSTRAINT FK_Shop_Storage_Location_Audit_id_location
FOREIGN KEY (id_location)
REFERENCES Shop_Storage_Location(id_location)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Storage_Location_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,13 +0,0 @@
-- Storage Location Temp
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Storage_Location_Temp';
CREATE TABLE IF NOT EXISTS Shop_Storage_Location (
id_location INT NOT NULL PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(500) NOT NULL,
active BIT NOT NULL DEFAULT 1
);

View File

@@ -0,0 +1,25 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Permission'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Permission (
id_permission INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, code VARCHAR(50)
, name VARCHAR(255)
, id_permission_group INT NOT NULL
, CONSTRAINT FK_PH_Permission_id_permission_group
FOREIGN KEY (id_permission_group)
REFERENCES partsltd_prod.PH_Permission_Group(id_group)
, id_access_level_required INT NOT NULL
, CONSTRAINT FK_PH_Permission_id_access_level_required
FOREIGN KEY (id_access_level_required)
REFERENCES partsltd_prod.PH_Access_Level(id_access_level)
, display_order INT NOT NULL
, active BIT NOT NULL DEFAULT 1
);

View File

@@ -1,29 +0,0 @@
-- Storage Location Branch
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Storage_Location_Branch';
CREATE TABLE IF NOT EXISTS Shop_Storage_Location_Branch (
id_branch INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_location_parent INT NOT NULL,
CONSTRAINT FK_Shop_Storage_Location_Branch_id_location_parent
FOREIGN KEY (id_location_parent)
REFERENCES Shop_Storage_Location(id_location)
ON UPDATE RESTRICT,
id_location_child INT NOT NULL,
CONSTRAINT FK_Shop_Storage_Location_Branch_id_location_child
FOREIGN KEY (id_location_child)
REFERENCES Shop_Storage_Location(id_location)
ON UPDATE RESTRICT,
-- depth INT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Storage_Location_Branch_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Storage Location Branch Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Storage_Location_Branch_Audit';
CREATE TABLE IF NOT EXISTS Shop_Storage_Location_Branch_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_branch INT NOT NULL,
CONSTRAINT FK_Shop_Storage_Location_Branch_Audit_id_branch
FOREIGN KEY (id_branch)
REFERENCES Shop_Storage_Location_Branch(id_branch)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Storage_Location_Branch_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,15 +0,0 @@
-- Storage Location Branch Temp
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Storage_Location_Branch_Temp';
CREATE TABLE IF NOT EXISTS Shop_Storage_Location_Branch_Temp (
id_branch INT NOT NULL PRIMARY KEY,
id_location_parent INT NOT NULL,
id_location_child INT NOT NULL,
-- depth INT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL
);

View File

@@ -1,23 +0,0 @@
-- Currencies
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Currency';
CREATE TABLE IF NOT EXISTS Shop_Currency (
id_currency INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(255) NOT NULL,
symbol VARCHAR(50) NOT NULL,
factor_from_GBP FLOAT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Currency_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
ON UPDATE RESTRICT
);

View File

@@ -0,0 +1,29 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_User'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_User (
id_user INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_user_auth0 VARCHAR(200)
, firstname VARCHAR(255)
, surname VARCHAR(255)
, email VARCHAR(254)
, is_email_verified BIT NOT NULL DEFAULT 0
, is_super_user BIT NOT NULL DEFAULT 0
, active BIT NOT NULL DEFAULT 1
, created_on DATETIME
, id_user_created_by INT
, CONSTRAINT FK_PH_User_id_user_created_by
FOREIGN KEY (id_user_created_by)
REFERENCES partsltd_prod.PH_User(id_user)
, id_change_set INT
, CONSTRAINT FK_PH_User_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.PH_User_Change_Set(id_change_set)
);

View File

@@ -1,23 +0,0 @@
-- Currency Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Currency_Audit';
CREATE TABLE IF NOT EXISTS Shop_Currency_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_currency INT NOT NULL,
CONSTRAINT FK_Shop_Currency_Audit_id_currency
FOREIGN KEY (id_currency)
REFERENCES Shop_Currency(id_currency)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Currency_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_User_Change_Set(id_change_set)
ON UPDATE RESTRICT
);

View File

@@ -1,16 +0,0 @@
-- Currency Temp
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Currency_Temp';
CREATE TABLE IF NOT EXISTS Shop_Currency_Temp (
id_currency INT NOT NULL PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(255) NOT NULL,
symbol VARCHAR(1) NOT NULL,
factor_from_GBP FLOAT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL
);

View File

@@ -0,0 +1,24 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_User_Audit'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_User_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_user INT NOT NULL
, CONSTRAINT FK_PH_User_Audit_id_user
FOREIGN KEY (id_user)
REFERENCES partsltd_prod.PH_User(id_user)
, name_field VARCHAR(50) NOT NULL
, value_prev VARCHAR(500)
, value_new VARCHAR(500)
, id_change_set INT NOT NULL
, CONSTRAINT FK_PH_User_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.PH_User_Change_Set(id_change_set)
);

View File

@@ -1,38 +0,0 @@
-- Taxes and Surcharges
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Tax_Or_Surcharge';
CREATE TABLE Shop_Tax_Or_Surcharge (
id_tax INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(200) NOT NULL,
id_region_buyer INT NOT NULL,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_id_region_buyer
FOREIGN KEY (id_region_buyer)
REFERENCES Shop_Region(id_region),
id_region_seller INT NOT NULL,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_id_region_seller
FOREIGN KEY (id_region_seller)
REFERENCES Shop_Region(id_region),
id_currency INT,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_id_currency
FOREIGN KEY (id_currency)
REFERENCES Shop_Currency(id_currency)
ON UPDATE RESTRICT,
fixed_fee FLOAT NOT NULL DEFAULT 0,
multiplier FLOAT NOT NULL DEFAULT 1 CHECK (multiplier > 0),
apply_fixed_fee_before_multiplier BIT DEFAULT 1,
quantity_min FLOAT NOT NULL DEFAULT 0,
quantity_max FLOAT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,22 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_User_Temp'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_User_Temp (
id_temp INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_user INT NOT NULL
, id_user_auth0 VARCHAR(200)
, firstname VARCHAR(255)
, surname VARCHAR(255)
, email VARCHAR(254)
, is_email_verified BIT
, is_super_user BIT
, active BIT
, guid BINARY(36) NOT NULL
);

View File

@@ -1,23 +0,0 @@
-- Tax Or Surcharge Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Tax_Or_Surcharge_Audit';
CREATE TABLE IF NOT EXISTS Shop_Tax_Or_Surcharge_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_tax INT NOT NULL,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_Audit_id_discount
FOREIGN KEY (id_tax)
REFERENCES Shop_Tax_Or_Surcharge(id_tax)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
ON UPDATE RESTRICT
);

View File

@@ -0,0 +1,26 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Role'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Role (
id_role INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, code VARCHAR(50)
, name VARCHAR(255)
, display_order INT NOT NULL
, active BIT NOT NULL DEFAULT 1
, created_on DATETIME
, id_user_created_by INT
, CONSTRAINT FK_PH_Role_id_user_created_by
FOREIGN KEY (id_user_created_by)
REFERENCES partsltd_prod.PH_User(id_user)
, id_change_set INT
, CONSTRAINT FK_PH_Role_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.PH_User_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Taxes and Surcharges Temp
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Tax_Or_Surcharge_Temp';
CREATE TABLE Shop_Tax_Or_Surcharge_Temp (
id_tax INT NOT NULL PRIMARY KEY,
code VARCHAR(50) NOT NULL,
name VARCHAR(200) NOT NULL,
id_region_buyer INT NOT NULL,
id_region_seller INT NOT NULL,
id_currency INT,
fixed_fee FLOAT NOT NULL DEFAULT 0,
multiplier FLOAT NOT NULL DEFAULT 1 CHECK (multiplier > 0),
apply_fixed_fee_before_multiplier BIT DEFAULT 1,
quantity_min FLOAT NOT NULL DEFAULT 0,
quantity_max FLOAT NOT NULL,
active BIT NOT NULL DEFAULT 1,
display_order INT NOT NULL
);

View File

@@ -0,0 +1,24 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Role_Audit'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Role_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_role INT NOT NULL
, CONSTRAINT FK_PH_Role_Audit_id_role
FOREIGN KEY (id_role)
REFERENCES partsltd_prod.PH_Role(id_role)
, name_field VARCHAR(50) NOT NULL
, value_prev VARCHAR(500)
, value_new VARCHAR(500)
, id_change_set INT NOT NULL
, CONSTRAINT FK_PH_Role_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.PH_User_Change_Set(id_change_set)
);

View File

@@ -1,26 +0,0 @@
-- Unit of Measurement
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Unit_Measurement';
CREATE TABLE IF NOT EXISTS Shop_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,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Unit_Measurement_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Unit of Measurement Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Unit_Measurement_Audit';
CREATE TABLE IF NOT EXISTS Shop_Unit_Measurement_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_unit_measurement INT NOT NULL,
CONSTRAINT FK_Shop_Unit_Measurement_Audit_id_unit_measurement
FOREIGN KEY (id_unit_measurement)
REFERENCES Shop_Unit_Measurement(id_unit_measurement)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Unit_Measurement_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,35 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Role_Permission_Link'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Role_Permission_Link (
id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_role INT NOT NULL
, CONSTRAINT FK_PH_Role_Permission_Link_id_role
FOREIGN KEY (id_role)
REFERENCES partsltd_prod.PH_Role(id_role)
, id_permission INT NOT NULL
, CONSTRAINT FK_PH_Role_Permission_Link_id_permission
FOREIGN KEY (id_permission)
REFERENCES partsltd_prod.PH_Permission(id_permission)
, id_access_level INT NOT NULL
, CONSTRAINT FK_PH_Role_Permission_Link_id_access_level
FOREIGN KEY (id_access_level)
REFERENCES partsltd_prod.PH_Access_Level(id_access_level)
, active BIT NOT NULL DEFAULT 1
, created_on DATETIME
, id_user_created_by INT
, CONSTRAINT FK_PH_Role_Permission_Link_id_user_created_by
FOREIGN KEY (id_user_created_by)
REFERENCES partsltd_prod.PH_User(id_user)
, id_change_set INT
, CONSTRAINT FK_PH_Role_Permission_Link_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.PH_User_Change_Set(id_change_set)
);

View File

@@ -1,23 +0,0 @@
-- Unit of Measurement Conversion
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Unit_Measurement_Conversion';
CREATE TABLE IF NOT EXISTS Shop_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,
created_on DATETIME,
created_by INT,
id_change_set INT,
CONSTRAINT FK_Shop_Unit_Measurement_Conversion_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,23 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Role_Permission_Link_Audit';
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Role_Permission_Link_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_link INT NOT NULL
, CONSTRAINT FK_PH_Role_Permission_Link_Audit_id_link
FOREIGN KEY (id_link)
REFERENCES partsltd_prod.PH_Role_Permission_Link(id_link)
, name_field VARCHAR(50) NOT NULL
, value_prev VARCHAR(500)
, value_new VARCHAR(500)
, id_change_set INT NOT NULL
, CONSTRAINT FK_PH_Role_Permission_Link_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.PH_User_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Unit of Measurement Conversion Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Unit_Measurement_Conversion_Audit';
CREATE TABLE IF NOT EXISTS Shop_Unit_Measurement_Conversion_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_conversion INT NOT NULL,
CONSTRAINT FK_Shop_Unit_Measurement_Conversion_Audit_id_conversion
FOREIGN KEY (id_conversion)
REFERENCES Shop_Unit_Measurement_Conversion(id_conversion)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(500),
value_new VARCHAR(500),
id_change_set INT NOT NULL,
CONSTRAINT FK_Shop_Unit_Measurement_Conversion_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,31 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_User_Role_Link'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_User_Role_Link (
id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_user INT NOT NULL
, CONSTRAINT FK_PH_User_Role_Link_id_user
FOREIGN KEY (id_user)
REFERENCES partsltd_prod.PH_User(id_user)
, id_role INT NOT NULL
, CONSTRAINT FK_PH_User_Role_Link_id_role
FOREIGN KEY (id_role)
REFERENCES partsltd_prod.PH_Role(id_role)
, active BIT NOT NULL DEFAULT 1
, created_on DATETIME
, id_user_created_by INT
, CONSTRAINT FK_PH_User_Role_Link_id_user_created_by
FOREIGN KEY (id_user_created_by)
REFERENCES partsltd_prod.PH_User(id_user)
, id_change_set INT
, CONSTRAINT FK_PH_User_Role_Link_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.PH_User_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,24 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_User_Role_Link_Audit'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_User_Role_Link_Audit (
id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, id_link INT NOT NULL
, CONSTRAINT FK_PH_User_Role_Link_Audit_id_link
FOREIGN KEY (id_link)
REFERENCES partsltd_prod.PH_User_Role_Link(id_link)
, name_field VARCHAR(50) NOT NULL
, value_prev VARCHAR(500)
, value_new VARCHAR(500)
, id_change_set INT NOT NULL
, CONSTRAINT FK_PH_User_Role_Link_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES partsltd_prod.PH_User_Change_Set(id_change_set)
);

View File

@@ -0,0 +1,22 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Calc_User_Temp'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Calc_User_Temp (
guid BINARY(36) NOT NULL
, id_user INT
, id_permission_required INT NOT NULL
, CONSTRAINT FK_PH_Calc_User_Temp_id_permission_required
FOREIGN KEY (id_permission_required)
REFERENCES partsltd_prod.PH_Permission (id_permission)
, priority_access_level_required INT NOT NULL
, is_super_user BIT
, priority_access_level_user INT
, has_access BIT
);

View File

@@ -0,0 +1,19 @@
USE partsltd_prod;
SELECT CONCAT('WARNING: Table ', TABLE_SCHEMA, '.', TABLE_NAME, ' already exists.') AS msg_warning
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'partsltd_prod'
AND TABLE_NAME = 'PH_Contact_Form_Change_Set'
;
CREATE TABLE IF NOT EXISTS partsltd_prod.PH_Contact_Form_Change_Set (
id_change_set INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, comment VARCHAR(500)
, updated_last_on DATETIME
, id_user_updated_last_by INT
, CONSTRAINT FK_PH_Role_id_user_updated_last_by
FOREIGN KEY (id_user_updated_last_by)
REFERENCES partsltd_prod.PH_User(id_user)
);

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