Fix: Cleanup \n 1. Remove PostgreSQL \n 2. Remove comments from Python \n 3. Remove non-demo ERP Python code \n 4. Remove deprecated Python code

This commit is contained in:
2025-03-21 13:33:29 +00:00
parent 2ddfd8e10f
commit a6cbf9a7b7
220 changed files with 151 additions and 34140 deletions

7
.gitignore vendored
View File

@@ -11,6 +11,7 @@ __pycache__/
# Ignore logs and databases
*.log
*.log.*
# Ignore logs and databases
# *.sql
@@ -58,13 +59,13 @@ TODO.md
tmp/
# Ignore all .txt files in the doc/ directory
doc/*.txt
static/docs/*.txt
# But don't ignore doc/important.txt, even though we're ignoring .txt files above
!doc/important.txt
!static/docs/important.txt
# Ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf
static/docs/**/*.pdf
# Ignore deprecated files
DEPRECATED/

View File

@@ -8,49 +8,40 @@ NOTE: ALL INSTRUCTIONS ARE FOR LINUX.
- Python 3.10
- npm
- Locally hosted MySQL database
- Auth0 application for project
- (Optional) Google ReCAPTCHA public and secret keys
- (Optional) Bot email account
## 1. Create Auth0 application for project
## 1. Create and populate database
1.1. Sign into your local MySQL workspace
1.2. Run script static/MySQL/0000_combined.sql
## 2. (Optional) Create Google reCAPTCHA service
NOTE: IF CONTACT US PAGE FORM FUNCTIONALITY IS REQUIRED, COMPLETE THIS STEP.
2.1. Go to the reCAPTCHA Admin Console and register your site: https://www.google.com/recaptcha/admin
2.2. Choose reCAPTCH v2
2.3. Generate and save keys for step 10
## 3. (Optional) Create bot email account
NOTE: IF CONTACT US PAGE FORM FUNCTIONALITY IS REQUIRED, COMPLETE THIS STEP.
3.1. Using your chosen email provider, create a new account for sending emails from the web server
## 4. Create and populate database
4.1. Sign into your local MySQL workspace
4.2. Run script static/MySQL/0000_combined.sql
## 5. Open the project in a new terminal window
5.1. Open a new terminal window
5.2. Navigate to the project with the following command
## 2. Open the project in a new terminal window
2.1. Open a new terminal window
2.2. Navigate to the project with the following command
- cd path/to/project/main/directory
## 6. Create virtual environment
6.1. Terminal command
## 3. Create virtual environment
3.1. Terminal command
- python3 -m venv env_demo_partsERP
## 7. Enter virtual environment
7.1. Terminal command
## 4. Enter virtual environment
4.1. Terminal command
- source env_demo_partsERP/bin/activate
## 8. Run module bundler
8.1. Terminal command
## 5. Run module bundler
5.1. Terminal command
- npm run build
## 9. Install required python packages
9.1. Terminal command
## 6. Install required python packages
6.1. Terminal command
- pip3 install -r requirements.txt
## 10. Set required environment variables
10.1. Terminal command
## 7. Set required environment variables
7.1. Terminal command
- export variable_name=variable_value
10.2. Required variables
7.2. Required variables
| Name | Purpose | Example Value |
| -------- | -------- | -------- |
| KEY_SECRET_FLASK | Private key for server encryption. | password123 |
@@ -60,7 +51,7 @@ NOTE: IF CONTACT US PAGE FORM FUNCTIONALITY IS REQUIRED, COMPLETE THIS STEP.
| SQLALCHEMY_DATABASE_URI | Database connection string for SQLAlchemy. | mysql://db_user_name:db_password@127.0.0.1:3306/db_name |
| URL_HOST | Domain (and port as necessary) that the project is hosted on. | https://127.0.0.1:5000/ |
10.3. Optional variables
7.3. Optional variables
| Name | Purpose | Example Value |
| -------- | -------- | -------- |
| MAIL_DEFAULT_SENDER | Bot email address. Required for sending internal emails following form completion on Contact Us page. | bot@partsltd.co.uk |
@@ -69,12 +60,12 @@ NOTE: IF CONTACT US PAGE FORM FUNCTIONALITY IS REQUIRED, COMPLETE THIS STEP.
| RECAPTCHA_PUBLIC_KEY | Public key for Google reCAPTCHA. Required for bot-prevention mesaures on Contact Us page form.| erDasdku8asdncuSAAS88... |
| RECAPTCHA_PRIVATE_KEY | Private key for Google reCAPTCHA. Required for bot-prevention mesaures on Contact Us page form. | erDasdku8asdncuSAAS8... |
## 11. Host project
NOTE: DO EITHER 11.1 OR 11.2.
11.1. Host for local machine
## 8. Host project
NOTE: DO EITHER 8.1 OR 8.2.
8.1. Host for local machine
- python3 -m flask run
11.2. Host for local network
8.2. Host for local network
- python3 -m flask run --host=0.0.0.0

27
app.py
View File

@@ -10,11 +10,6 @@ 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
# internal
from config import app_config, Config
from controllers.core import routes_core
@@ -33,7 +28,6 @@ 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
# from flask_appconfig import AppConfig
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from flask_mail import Mail, Message
@@ -46,17 +40,13 @@ from logging.handlers import RotatingFileHandler
import traceback
import logging
sys.path.insert(0, os.path.dirname(__file__)) # Todo: why?
sys.path.insert(0, os.path.dirname(__file__))
app = Flask(__name__)
# AppConfig(app)
app.config.from_object(app_config) # for db init with required keys
app.config.from_object(app_config)
app.app_config = app_config
# app.config["config"] = app_config()
# logging
handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=3)
handler.setLevel(logging.DEBUG)
app.logger.addHandler(handler)
@@ -82,6 +72,8 @@ def make_session_permanent():
session.permanent = True
csrf = CSRFProtect()
csrf.init_app(app)
cors = CORS(app, resources={
r"/static/*": {
"origins": [app.config["URL_HOST"]],
@@ -89,15 +81,15 @@ cors = CORS(app, resources={
"max_age": 3600
}
})
csrf.init_app(app)
cors.init_app(app)
db.init_app(app)
mail.init_app(app)
oauth.init_app(app)
mail.init_app(app)
with app.app_context():
# config = app.config["config"]
db.create_all()
db.engine.url = app.config['SQLALCHEMY_DATABASE_URI']
@@ -114,7 +106,6 @@ with app.app_context():
access_token_url = f'https://{app.config["DOMAIN_AUTH0"]}/oauth/token',
)
app.register_blueprint(routes_core)
app.register_blueprint(routes_legal)
app.register_blueprint(routes_store)
@@ -138,9 +129,7 @@ def console_log(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

@@ -37,8 +37,6 @@ class Address(db.Model, Base):
county = db.Column(db.String(256))
active = db.Column(db.Boolean)
# region = None
def __init__(self):
super().__init__()
Base.__init__(self)

View File

@@ -67,10 +67,6 @@ 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'
"""
NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'name-attribute-option-text'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = 'name-attribute-option-value'
"""
def __repr__(self):
attrs = '\n'.join(f'{k}={v!r}' for k, v in self.__dict__.items())
return f'<{self.__class__.__name__}(\n{attrs}\n)>'

View File

@@ -17,29 +17,6 @@ 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'

View File

@@ -32,28 +32,13 @@ class Get_Many_Parameters_Base(BaseModel, metaclass=ABCMeta):
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
class SQLAlchemy_ABC(db.Model, metaclass=SQLAlchemy_ABCMeta):
__abstract__ = True
# id = db.Column(db.Integer, primary_key=True)
def __init__(self):
pass
def __repr__(self):
@@ -63,10 +48,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

@@ -27,8 +27,6 @@ class Region(db.Model, Base):
code = db.Column(db.String(50))
name = db.Column(db.String(200))
active = db.Column(db.Boolean)
# region = None
def __init__(self):
super().__init__()

View File

@@ -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)
@@ -35,22 +33,6 @@ class SQL_Error(db.Model):
name = db.Column(db.String(500))
description = db.Column(db.String(4000))
"""
def __new__(cls, display_order, code, msg):
_m = 'SQL_Error.__new__'
v_arg_type = 'class attribute'
av.val_int(display_order, 'display_order', _m)
av.val_str(code, 'code', _m, max_len=50, v_arg_type=v_arg_type)
av.val_str(msg, 'msg', _m, max_len=4000, v_arg_type=v_arg_type)
return super(SQL_Error, cls).__new__(cls)
def __init__(self, display_order, code, msg):
self.display_order = display_order
self.code = code
self.msg = msg
super().__init__()
"""
def from_DB_record(record):
error = SQL_Error()
error.display_order = record[0]

View File

@@ -1,184 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Basket Business Object
Description:
Business object for basket
"""
# IMPORTS
# VARIABLE INSTANTIATION
# CLASSES
# METHODS
# IMPORTS
# internal
import lib.argument_validation as av
# from lib import data_types
from business_objects.store.product import Product #, Parameters_Product
from business_objects.store.discount import Discount
from business_objects.store.delivery_option import Delivery_Option
from business_objects.store.store_base import Store_Base
# from forms import Form_Product
# from models.model_view_store import Model_View_Store # circular
# from datastores.datastore_store import DataStore_Store # circular
# from forms import Form_Basket_Add, Form_Basket_Edit # possibly circular
from helpers.helper_app import Helper_App
# external
# from enum import Enum
from flask import jsonify
import locale
# VARIABLE INSTANTIATION
# CLASSES
class Basket_Item():
product: Product
quantity: int
delivery_option: Delivery_Option
discounts: list
# form: Form_Product
is_included_VAT: bool
"""
def __init__(self):
self.is_unavailable_in_currency_or_region = False
self.is_available = True
"""
def from_product_and_quantity_and_VAT_included(product, quantity, is_included_VAT):
# Initialiser - validation
_m = 'Basket_Item.from_product_and_quantity'
v_arg_type = 'class attribute'
av.val_instance(product, 'product', _m, Product, v_arg_type=v_arg_type)
av.full_val_float(quantity, 'quantity', _m, product.get_quantity_min(), v_arg_type=v_arg_type)
basket_item = Basket_Item()
basket_item.product = product
basket_item.quantity = quantity
basket_item.is_included_VAT = is_included_VAT
return basket_item
def add_product_price_discount(self, discount):
av.val_instance(discount, 'discount', 'Basket_Item.add_product_price_discount', Discount, v_arg_type='class attribute')
self.discounts.append(discount)
def set_delivery_option(self, delivery_option):
av.val_instance(delivery_option, 'delivery_option', 'Basket_Item.set_delivery_option', Delivery_Option, v_arg_type='class attribute')
self.delivery_option = delivery_option
def update_quantity(self, quantity):
_m = 'Basket_Item.update_quantity'
v_arg_type = 'class attribute'
av.full_val_float(quantity, 'quantity', _m, self.product.get_quantity_min(), v_arg_type=v_arg_type)
self.quantity = quantity
def jsonify(self):
return jsonify(self)
def to_json(self):
permutation = self.product.get_permutation_selected()
return {
'product_id': self.product.id_product,
'permutation_id': permutation.id_permutation,
'price': permutation.output_price(self.is_included_VAT),
'quantity': self.quantity
}
def get_subtotal(self):
permutation = self.product.get_permutation_selected()
return round(self.product.get_price_local(self.is_included_VAT) * self.quantity, 2) if permutation.is_available else 0
def output_currency(self):
return self.product.output_currency()
def output_subtotal(self):
locale.setlocale(locale.LC_ALL, '')
subtotal = self.get_subtotal()
permutation = self.product.get_permutation_selected()
return 'Not available in this currency or region' if permutation.is_unavailable_in_currency_or_region else 'Not available' if not permutation.is_available else f'{self.product.output_currency()} {locale.format_string("%d", subtotal, grouping=True)}'
def __repr__(self):
return f'''
product: {self.product}
quantity: {self.quantity}
subtotal: {self.get_subtotal()}
'''
class Basket(Store_Base):
KEY_BASKET: str = 'basket'
KEY_ID_CURRENCY: str = 'id_currency'
KEY_ID_REGION_DELIVERY: str = 'id_region_delivery'
KEY_IS_INCLUDED_VAT: str = 'is_included_VAT'
KEY_ITEMS: str = 'items'
items: list
is_included_VAT: bool
id_region_delivery: int
id_currency: int
def __init__(self, is_included_VAT, id_currency, id_region_delivery):
self.items = []
self.is_included_VAT = is_included_VAT
self.id_currency = id_currency
self.id_region_delivery = id_region_delivery
def add_item(self, item):
av.val_instance(item, 'item', 'Basket.add_item', Basket_Item)
self.items.append(item)
def to_csv(self):
ids_permutation = ''
quantities_permutation = ''
for b_i in range(len(self.items)):
basket_item = self.items[b_i]
product = basket_item.product
if b_i > 0:
ids_permutation += ','
quantities_permutation += ','
ids_permutation += str(product.get_id_permutation())
quantities_permutation += str(basket_item.quantity)
Helper_App.console_log(f'ids_permutation_basket = {ids_permutation}')
Helper_App.console_log(f'quantities_permutation_basket = {quantities_permutation}')
return ids_permutation, quantities_permutation
def to_json_list(self):
json_list = []
for item in self.items:
json_list.append(item.to_json())
return json_list
def to_json(self):
return {
**self.get_shared_json_attributes(self),
Basket.KEY_ITEMS: self.to_json_list(),
Basket.KEY_IS_INCLUDED_VAT: self.is_included_VAT,
Basket.KEY_ID_CURRENCY: self.id_currency,
Basket.KEY_ID_REGION_DELIVERY: self.id_region_delivery
}
def output_total(self):
sum = 0
for b_i in self.items:
sum += b_i.get_subtotal()
symbol = self.items[0].output_currency() if len(self.items) > 0 else ''
return f'{symbol} {locale.format_string("%d", sum, grouping=True)}'
def len(self):
return len(self.items)
"""
def get_key_product_index_from_ids_product_permutation(id_product, id_permutation):
return f'{id_product},{"" if id_permutation is None else id_permutation}'
"""
def __repr__(self):
repr = f'Basket:'
for basket_item in self.items:
Helper_App.console_log(f'{basket_item}')
repr = f'{repr}\n{basket_item}'
return repr
def get_ids_permutation_unavailable(self):
ids_permutation = []
for item in self.items:
permutation = item.product.get_permutation_selected()
if not permutation.is_available:
ids_permutation.append(permutation.id_permutation)
return ids_permutation

View File

@@ -1,98 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Product Delivery Option Business Object
Description:
Business object for delivery option
"""
# internal
from extensions import db
# CLASSES
"""
class Delivery_Option():
name: str
delay_min: int # days
delay_max: int
quantity_min: float
quantity_max: float
regions: list # [Enum_Region]
cost: float
def __new__(cls, name, delay_min, delay_max, quantity_min, quantity_max, regions, cost):
_m = 'Delivery_Option.__new__'
v_arg_type = 'class attribute'
av.val_str(name, 'name', _m, v_arg_type = v_arg_type)
av.val_int(delay_min, 'delay_min', _m, 0, v_arg_type = v_arg_type)
av.val_int(delay_max, 'delay_max', _m, 0, v_arg_type = v_arg_type)
av.val_float(quantity_min, 'quantity_min', _m, 0, v_arg_type = v_arg_type)
av.val_float(quantity_max, 'quantity_max', _m, 0, v_arg_type = v_arg_type)
av.val_list_instances(regions, 'regions', _m, Enum_Region, v_arg_type = v_arg_type)
av.val_float(cost, 'cost', _m, 0, v_arg_type = v_arg_type)
return super(Delivery_Option, cls).__new__(cls)
def __init__(self, name, delay_min, delay_max, quantity_min, quantity_max, regions, cost):
self.name = name
self.delay_min = delay_min
self.delay_max = delay_max
self.quantity_min = quantity_min
self.quantity_max = quantity_max
self.regions = regions
self.cost = cost
"""
class Delivery_Option(db.Model):
id_option = db.Column(db.Integer, primary_key=True)
id_product = db.Column(db.Integer)
id_permutation = db.Column(db.Integer)
id_category = db.Column(db.Integer)
code = db.Column(db.String(50))
name = db.Column(db.String(100))
latency_min = db.Column(db.Integer)
latency_max = db.Column(db.Integer)
quantity_min = db.Column(db.Integer)
quantity_max = db.Column(db.Integer)
codes_region = db.Column(db.String(4000))
names_region = db.Column(db.String(4000))
price_GBP = db.Column(db.Float)
display_order = db.Column(db.Integer)
def __init__(self):
self.delivery_regions = []
def from_DB_get_many_product_catalogue(query_row):
option = Delivery_Option()
option.id_option = query_row[0]
option.id_product = query_row[1]
option.id_permutation = query_row[2]
option.id_category = query_row[3]
option.code = query_row[4]
option.name = query_row[5]
option.latency_min = query_row[6]
option.latency_max = query_row[7]
option.quantity_min = query_row[8]
option.quantity_max = query_row[9]
option.codes_region = query_row[10]
option.names_region = query_row[11]
option.price_GBP = query_row[12]
option.display_order = query_row[13]
return option
def __repr__(self):
return f'''
id: {self.id_option}
id_product: {self.id_product}
id_category: {self.id_category}
name: {self.name}
code: {self.code}
latency_min: {self.latency_min}
latency_max: {self.latency_max}
quantity_min: {self.quantity_min}
quantity_max: {self.quantity_max}
codes_region: {self.codes_region}
names_region: {self.names_region}
price_GBP: {self.price_GBP}
display_order: {self.display_order}
'''

View File

@@ -59,25 +59,7 @@ class Image(db.Model, Store_Base):
url = db.Column(db.String(255))
active = db.Column(db.Boolean)
display_order = db.Column(db.Integer)
"""
def __new__(cls, id, id_product, id_category, url, display_order):
_m = 'Image.__new__'
v_arg_type = 'class attribute'
av.val_int(id, 'id', _m, 0, v_arg_type=v_arg_type)
av.val_int(id_product, 'id_product', _m, 0, v_arg_type=v_arg_type)
av.val_int(id_category, 'id_category', _m, 0, v_arg_type=v_arg_type)
av.val_str(url, 'url', _m, max_len=254, v_arg_type=v_arg_type)
av.val_int(display_order, 'display_order', _m, v_arg_type=v_arg_type)
return super(Image, cls).__new__(cls)
def __init__(self, id, id_product, id_category, url, display_order):
self.id_image = id
self.id_product = id_product
self.id_category = id_category
self.url = url
self.display_order = display_order
super().__init__()
"""
def from_DB_get_many_product_catalogue(query_row):
_m = 'Image.from_DB_get_many_product_catalogue'
# Helper_App.console_log(f'image: {query_row}')

View File

@@ -302,12 +302,6 @@ class Manufacturing_Purchase_Order_Product_Link_Temp(db.Model, Store_Base):
id_unit_latency_manufacture = db.Column(db.Integer)
latency_manufacture: int = db.Column(db.Integer)
display_order: int = db.Column(db.Integer)
"""
cost_unit_local_VAT_excl: float = db.Column(db.Float)
cost_unit_local_VAT_incl: float = db.Column(db.Float)
price_unit_local_VAT_excl: float = db.Column(db.Float)
price_unit_local_VAT_incl: float = db.Column(db.Float)
"""
active: bool = db.Column(db.Boolean)
guid: str = db.Column(db.String(36))
def __init__(self):
@@ -328,12 +322,6 @@ class Manufacturing_Purchase_Order_Product_Link_Temp(db.Model, Store_Base):
row.id_unit_latency_manufacture = manufacturing_purchase_order_product_link.id_unit_latency_manufacture
row.latency_manufacture = manufacturing_purchase_order_product_link.latency_manufacture
row.display_order = manufacturing_purchase_order_product_link.display_order
"""
row.cost_unit_local_VAT_excl = manufacturing_purchase_order_product_link.cost_unit_local_VAT_excl
row.cost_unit_local_VAT_incl = manufacturing_purchase_order_product_link.cost_unit_local_VAT_incl
row.price_unit_local_VAT_excl = manufacturing_purchase_order_product_link.price_unit_local_VAT_excl
row.price_unit_local_VAT_incl = manufacturing_purchase_order_product_link.price_unit_local_VAT_incl
"""
row.active = 1 if manufacturing_purchase_order_product_link.active else 0
return row
def __repr__(self):

View File

@@ -1,89 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Order Business Object
Description:
Business object for order
"""
# internal
import lib.argument_validation as av
# from lib import data_types
from business_objects.store.product import Product
from business_objects.store.delivery_option import Delivery_Option
from business_objects.store.store_base import Store_Base
# from forms import Form_Product
# from models.model_view_store import Model_View_Store # circular
# external
# from enum import Enum
from flask import jsonify
import locale
# VARIABLE INSTANTIATION
# CLASSES
class Order(Store_Base):
category: str
product: Product
quantity: int
subtotal: float
delivery_option: Delivery_Option
# form: Form_Product
def __new__(cls, category, product, quantity):
# Initialiser - validation
_m = 'Product.__new__'
v_arg_type = 'class attribute'
av.val_str(category, 'category', _m, v_arg_type=v_arg_type)
av.val_instance(product, 'product', _m, Product, v_arg_type=v_arg_type)
av.full_val_float(quantity, 'quantity', _m, product.quantity_min, v_arg_type=v_arg_type)
return super(Basket_Item, cls).__new__(cls)
def __init__(self, category, product, quantity):
# Constructor
self.category = category
self.product = product
self.quantity = quantity
self.subtotal = round(self.product.price_GBP_full * self.quantity, 2)
"""
self.form = Form_Product()
if self.form.validate_on_submit():
# Handle form submission
pass
"""
def update_quantity(self, quantity):
_m = 'Basket_Item.update_quantity'
v_arg_type = 'class attribute'
av.full_val_float(quantity, 'quantity', _m, self.product.quantity_min, v_arg_type=v_arg_type)
self.quantity = quantity
self.subtotal = round(self.product.price_GBP_full * self.quantity, 2)
def jsonify(self):
return jsonify(self)
def to_json(self):
return {
**self.get_shared_json_attributes(self),
'product_id': self.product.id_product,
'price': self.product.price_GBP_full,
'quantity': self.quantity
}
def output_subtotal(self):
locale.setlocale(locale.LC_ALL, '')
return locale.format_string("%d", self.subtotal, grouping=True)
def __repr__(self):
return f'''
category: {self.category}
product: {self.product}
quantity: {self.quantity}
subtotal: {self.subtotal}
'''

View File

@@ -32,28 +32,7 @@ from helpers.helper_app import Helper_App
# external
from dataclasses import dataclass
from typing import ClassVar, List
"""
class Enum_Status_Stock(Enum):
OUT = 0
LOW = 1
IN = 99
def text(self):
return Enum_Status_Stock.Enum_Status_Stock_Text(self)
def Enum_Status_Stock_Text(status):
av.val_instance(status, 'category', 'Enum_Status_Stock_Text', Enum_Status_Stock)
if status == Enum_Status_Stock.OUT:
return 'Out of stock'
elif status == Enum_Status_Stock.LOW:
return 'Low on stock'
else:
return 'Fully stocked'
def get_member_by_text(text):
return data_types.get_enum_member_by_text(Enum_Status_Stock, text.upper())
"""
class Product(SQLAlchemy_ABC, Store_Base):
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT
NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME
@@ -70,16 +49,6 @@ class Product(SQLAlchemy_ABC, Store_Base):
can_view = db.Column(db.Boolean)
can_edit = db.Column(db.Boolean)
can_admin = db.Column(db.Boolean)
# form_basket_add: Form_Basket_Add
# form_basket_edit: Form_Basket_Edit
# has_variations: bool
# index_permutation_selected: int
"""
permutations: list = None
permutation_index: dict = None
variation_trees: list = None
"""
def __init__(self):
self.permutations = []
@@ -109,24 +78,6 @@ class Product(SQLAlchemy_ABC, Store_Base):
product.can_edit = av.input_bool(query_row[9], "can_edit", _m, v_arg_type=v_arg_type)
product.can_admin = av.input_bool(query_row[10], "can_admin", _m, v_arg_type=v_arg_type)
return product
"""
def from_permutation(permutation, has_variations = False):
_m = 'Product.from_permutation'
v_arg_type = 'class attribute'
av.val_instance(permutation, 'permutation', _m, Product_Permutation, v_arg_type=v_arg_type)
product = Product()
product.has_variations = has_variations
product.index_permutation_selected = 0
product.id_product = permutation.id_product
product.id_category = permutation.id_category
product.display_order = permutation.display_order
product.can_view = permutation.can_view
product.can_edit = permutation.can_edit
product.can_admin = permutation.can_admin
product.permutations.append(permutation)
# product.get_variation_trees()
return product
"""
def add_product_permutation(self, permutation):
_m = 'Product.add_product_permutation'
av.val_instance(permutation, 'permutation', _m, Product_Permutation)
@@ -136,36 +87,9 @@ class Product(SQLAlchemy_ABC, Store_Base):
except KeyError:
self.permutation_index[permutation.id_permutation] = len(self.permutations)
self.permutations.append(permutation)
"""
if self.has_variations:
self.has_variations = False
"""
if self.index_permutation_selected is None:
self.index_permutation_selected = self.permutation_index[permutation.id_permutation]
Helper_App.console_log(f'setting selected permutation for product {self.id_product} to {self.index_permutation_selected}') # :\n{self.permutations[self.index_permutation_selected]}
"""
def from_permutations(permutations):
_m = 'Product.from_permutations'
v_arg_type = 'class attribute'
if len(permutations) == 0:
raise ValueError(av.error_msg_str(permutations, 'permutations', _m, list, v_arg_type=v_arg_type))
product = Product()
product.has_variations = True
product.index_permutation_selected = 0
product.id_product = permutations[0].id_product
product.id_category = permutations[0].id_category
product.display_order = permutations[0].display_order
product.can_view = True
product.can_edit = True
product.can_admin = True
for permutation in permutations:
product.can_view &= permutation.can_view
product.can_edit &= permutation.can_edit
product.can_admin &= permutation.can_admin
product.permutations.append(permutations)
product.get_variation_trees()
return product
"""
Helper_App.console_log(f'setting selected permutation for product {self.id_product} to {self.index_permutation_selected}')
def get_variation_trees(self):
self.variation_trees = []
for index_permutation in range(len(self.permutations)):
@@ -186,12 +110,6 @@ class Product(SQLAlchemy_ABC, Store_Base):
permutation = Product_Permutation.from_DB_Stripe_price(query_row)
product = Product.from_permutation(permutation)
return product
"""
def from_json(json_basket_item, key_id_product, key_id_permutation):
permutation = Product_Permutation.from_json(json_basket_item, key_id_product, key_id_permutation)
product = Product.from_permutation(permutation)
return product
"""
@classmethod
def from_json(cls, json):
product = cls()
@@ -242,13 +160,7 @@ class Product(SQLAlchemy_ABC, Store_Base):
return self.get_permutation_selected().description
def output_currency(self):
return self.get_permutation_selected().get_price().symbol_currency
"""
def add_form_basket_add(self):
self.form_basket_add = None
def add_form_basket_edit(self):
self.form_basket_edit = None
"""
def __repr__(self):
return f'''Product
id_product: {self.id_product}
@@ -263,23 +175,7 @@ class Product(SQLAlchemy_ABC, Store_Base):
variation trees: {self.variation_trees}
active: {self.active}
'''
"""
def get_index_permutation_from_id(self, id_permutation):
if id_permutation is None and not self.has_variations:
return 0
for index_permutation in range(len(self.permutations)):
permutation = self.permutations[index_permutation]
if permutation.id_permutation == id_permutation:
return index_permutation
raise ValueError(f"{av.error_msg_str(id_permutation, 'id_permutation', 'Product.get_index_permutation_from_id', int)}\nPermutation ID not found.")
"""
"""
def add_product_variation(self, variation):
av.val_instance(variation, 'variation', 'Product.add_product_variation', Product_Variation)
# Helper_App.console_log(f'variation: {variation}')
index_permutation = self.permutation_index[variation.id_permutation] # self.get_index_permutation_from_id(variation.id_permutation)
self.permutations[index_permutation].add_product_variation(variation)
"""
def add_product_variation_type(self, variation_type):
variation = variation_type.variations[0]
index_permutation = self.permutation_index[variation.id_permutation]
@@ -318,27 +214,7 @@ class Product(SQLAlchemy_ABC, Store_Base):
for permutation in self.permutations:
list_rows.append(permutation.to_row_permutation())
return list_rows
"""
@classmethod
def from_json(cls, json):
product = cls()
product.id_product = json[cls.ATTR_ID_PRODUCT]
product.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
product.name = json[cls.FLAG_NAME]
product.display_order = json[cls.FLAG_DISPLAY_ORDER]
product.can_view = json[cls.FLAG_CAN_VIEW]
product.can_edit = json[cls.FLAG_CAN_EDIT]
product.can_admin = json[cls.FLAG_CAN_ADMIN]
product.has_variations = json[cls.FLAG_HAS_VARIATIONS]
product.index_permutation_selected = json[cls.FLAG_INDEX_PERMUTATION_SELECTED]
product.permutations = []
for json_permutation in json[cls.ATTR_ID_PRODUCT_PERMUTATION]:
product.permutations.append(Product_Permutation.from_json(json_permutation))
product.variation_trees = []
for json_tree in json[cls.FLAG_PRODUCT_VARIATION_TREES]:
product.variation_trees.append(Product_Variation_Tree.from_json(json_tree))
return product
"""
def to_json(self):
return {
**self.get_shared_json_attributes(self),
@@ -366,22 +242,7 @@ class Product(SQLAlchemy_ABC, Store_Base):
if type not in list_types:
list_types.append(type)
return list_types
"""
def get_json_str_types_variation_trees(self):
json_str = ''
for tree in self.variation_trees:
if json_str != '':
json_str += '\n'
json_str += tree.get_json_str_types()
return json_str
def get_text_input_variation_types(self):
text_input = ''
for tree in self.variation_trees:
if text_input != '':
text_input += '\n'
text_input += tree.get_text_input_types()
return text_input
"""
def get_csv_ids_permutation(self):
csv = ''
for permutation in self.permutations:
@@ -392,36 +253,18 @@ class Product(SQLAlchemy_ABC, Store_Base):
class Parameters_Product(Get_Many_Parameters_Base):
# id_user: str
get_all_product_category: bool
get_inactive_product_category: bool
# get_first_product_category_only: bool
ids_product_category: str
get_all_product: bool
get_inactive_product: bool
# get_first_product_only: bool
ids_product: str
get_all_permutation: bool
get_inactive_permutation: bool
# get_first_permutation_only: bool
ids_permutation: str
get_all_image: bool
get_inactive_image: bool
# get_first_image_only: bool
ids_image: str
"""
get_all_region: bool
get_inactive_region: bool
get_first_region_only: bool
ids_region: str
get_all_currency: bool
get_inactive_currency: bool
get_first_currency_only: bool
ids_currency: str
get_all_discount: bool
get_inactive_discount: bool
ids_discount: str
"""
get_products_quantity_stock_below_min: bool
def to_json(self):
@@ -429,37 +272,21 @@ class Parameters_Product(Get_Many_Parameters_Base):
# 'a_id_user': None,
'a_get_all_product_category': self.get_all_product_category,
'a_get_inactive_product_category': self.get_inactive_product_category,
# 'a_get_first_product_category_only': self.get_first_product_category_only,
'a_ids_product_category': self.ids_product_category,
'a_get_all_product': self.get_all_product,
'a_get_inactive_product': self.get_inactive_product,
# 'a_get_first_product_only': self.get_first_product_only,
'a_ids_product': self.ids_product,
'a_get_all_permutation': self.get_all_permutation,
'a_get_inactive_permutation': self.get_inactive_permutation,
# 'a_get_first_permutation_only': self.get_first_permutation_only,
'a_ids_permutation': self.ids_permutation,
'a_get_all_image': self.get_all_image,
'a_get_inactive_image': self.get_inactive_image,
# 'a_get_first_image_only': self.get_first_image_only,
'a_ids_image': self.ids_image,
# 'a_get_all_delivery_region': self.get_all_region,
# 'a_get_inactive_delivery_region': self.get_inactive_region,
# 'a_get_first_delivery_region_only': self.get_first_region_only,
# 'a_ids_delivery_region': self.ids_region,
# 'a_get_all_currency': self.get_all_currency,
# 'a_get_inactive_currency': self.get_inactive_currency,
# 'a_get_first_currency_only': self.get_first_currency_only,
# 'a_ids_currency': self.ids_currency,
# 'a_get_all_discount': self.get_all_discount,
# 'a_get_inactive_discount': self.get_inactive_discount,
# 'a_ids_discount': self.ids_discount,
'a_get_products_quantity_stock_below_min': self.get_products_quantity_stock_below_min
}
@staticmethod
def from_form_filters_product(form):
# if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product)
has_filter_category = not (form.id_category.data == '0' or form.id_category.data == '' or form.id_category.data is None)
is_not_empty = av.input_bool(form.is_not_empty.data, "is_not_empty", "Parameters_Product.from_form_filters_product")
@@ -467,37 +294,20 @@ class Parameters_Product(Get_Many_Parameters_Base):
return Parameters_Product(
get_all_product_category = not has_filter_category,
get_inactive_product_category = not active,
# get_first_product_category_only = False,
ids_product_category = form.id_category.data if form.id_category.data is not None else '',
get_all_product = True,
get_inactive_product = not active,
# get_first_product_only = False,
ids_product = '',
get_all_permutation = True,
get_inactive_permutation = not active,
# get_first_permutation_only = False,
ids_permutation = '',
get_all_image = False,
get_inactive_image = False,
# get_first_image_only = False,
ids_image = '',
# get_all_region = False,
# get_inactive_region = False,
# get_first_region_only = False,
# ids_region = '',
# get_all_currency = False,
# get_inactive_currency = False,
# get_first_currency_only = False,
# ids_currency = '',
# get_all_discount = False,
# get_inactive_discount = False,
# ids_discount = '',
get_products_quantity_stock_below_min = False
)
@staticmethod
def from_form_filters_product_permutation(form):
# if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
# av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product_Permutation)
has_category_filter = not (form.id_category.data == '0' or form.id_category.data == '' or form.id_category.data is None)
has_product_filter = not (form.id_product.data == '0' or form.id_product.data == '' or form.id_product.data is None)
get_permutations_stock_below_min = av.input_bool(form.is_out_of_stock.data, "is_out_of_stock", "Parameters_Product.from_form_filters_product_permutation")
@@ -506,31 +316,16 @@ class Parameters_Product(Get_Many_Parameters_Base):
return Parameters_Product(
get_all_product_category = not has_category_filter,
get_inactive_product_category = get_inactive,
# get_first_product_category_only = False,
ids_product_category = form.id_category.data if form.id_category.data is not None else '',
get_all_product = not has_product_filter,
get_inactive_product = get_inactive,
# get_first_product_only = False,
ids_product = form.id_product.data if form.id_product.data is not None else '',
get_all_permutation = not get_permutations_stock_below_min,
get_inactive_permutation = get_inactive,
# get_first_permutation_only = False,
ids_permutation = '',
get_all_image = False,
get_inactive_image = False,
# get_first_image_only = False,
ids_image = '',
# get_all_region = False,
# get_inactive_region = False,
# get_first_region_only = False,
# ids_region = '',
# get_all_currency = False,
# get_inactive_currency = False,
# get_first_currency_only = False,
# ids_currency = '',
# get_all_discount = False,
# get_inactive_discount = False,
# ids_discount = '',
get_products_quantity_stock_below_min = get_permutations_stock_below_min
)
@@ -539,31 +334,16 @@ class Parameters_Product(Get_Many_Parameters_Base):
return Parameters_Product(
get_all_product_category = True,
get_inactive_product_category = False,
# get_first_product_category_only = False,
ids_product_category = '',
get_all_product = True,
get_inactive_product = False,
# get_first_product_only = False,
ids_product = '',
get_all_permutation = True,
get_inactive_permutation = False,
# get_first_permutation_only = False,
ids_permutation = '',
get_all_image = True,
get_inactive_image = False,
# get_first_image_only = False,
ids_image = '',
# get_all_region = True,
# et_inactive_region = False,
# get_first_region_only = False,
# ids_region = '',
# get_all_currency = True,
# get_inactive_currency = False,
# get_first_currency_only = False,
# ids_currency = '',
# get_all_discount = True,
# get_inactive_discount = False,
# ids_discount = '',
get_products_quantity_stock_below_min = True
)
@@ -572,31 +352,16 @@ class Parameters_Product(Get_Many_Parameters_Base):
return cls(
get_all_product_category = json.get('a_get_all_product_category', False),
get_inactive_product_category = json.get('a_get_inactive_product_category', False),
# get_first_product_category_only = json.get('a_get_first_product_category_only', False),
ids_product_category = json.get('a_ids_product_category', ''),
get_all_product = json.get('a_get_all_product', False),
get_inactive_product = json.get('a_get_inactive_product', False),
# get_first_product_only = json.get('a_get_first_product_only', False),
ids_product = json.get('a_ids_product', ''),
get_all_permutation = json.get('a_get_all_permutation', False),
get_inactive_permutation = json.get('a_get_inactive_permutation', False),
# get_first_permutation_only = json.get('a_get_first_permutation_only', False),
ids_permutation = json.get('a_ids_permutation', ''),
get_all_image = json.get('a_get_all_image', False),
get_inactive_image = json.get('a_get_inactive_image', False),
# get_first_image_only = json.get('a_get_first_image_only', False),
ids_image = json.get('a_ids_image', ''),
# get_all_region = json.get('a_get_all_region', False),
# get_inactive_region = json.get('a_get_inactive_region', False),
# get_first_region_only = json.get('a_get_first_region_only', False),
# ids_region = json.get('a_ids_region', ''),
# get_all_currency = json.get('a_get_all_currency', False),
# get_inactive_currency = json.get('a_get_inactive_currency', False),
# get_first_currency_only = json.get('a_get_first_currency_only', False),
# ids_currency = json.get('a_ids_currency', ''),
# get_all_discount = json.get('a_get_all_discount', False),
# get_inactive_discount = json.get('a_get_inactive_discount', False),
# ids_discount = json.get('a_ids_discount', ''),
get_products_quantity_stock_below_min = json.get('a_get_products_quantity_stock_below_min', False)
)
@@ -621,242 +386,6 @@ class Parameters_Product(Get_Many_Parameters_Base):
def from_filters_stock_item(cls, filters_stock_item):
return cls.from_form_filters_product_permutation(filters_stock_item)
"""
class Parameters_Product(Get_Many_Parameters_Base):
# id_user: str
get_all_product_category: bool
get_inactive_product_category: bool
# get_first_product_category_only: bool
ids_product_category: str
get_all_product: bool
get_inactive_product: bool
# get_first_product_only: bool
ids_product: str
get_all_permutation: bool
get_inactive_permutation: bool
# get_first_permutation_only: bool
ids_permutation: str
get_all_image: bool
get_inactive_image: bool
# get_first_image_only: bool
ids_image: str
""
get_all_region: bool
get_inactive_region: bool
get_first_region_only: bool
ids_region: str
get_all_currency: bool
get_inactive_currency: bool
get_first_currency_only: bool
ids_currency: str
get_all_discount: bool
get_inactive_discount: bool
ids_discount: str
""
get_products_quantity_stock_below_min: bool
def __init__(self, a_id_user, **kwargs):
super().__init__(a_id_user, **kwargs)
def to_json(self):
return {
'a_id_user': self.a_id_user,
'a_get_all_product_category': self.get_all_product_category,
'a_get_inactive_product_category': self.get_inactive_product_category,
# 'a_get_first_product_category_only': self.get_first_product_category_only,
'a_ids_product_category': self.ids_product_category,
'a_get_all_product': self.get_all_product,
'a_get_inactive_product': self.get_inactive_product,
# 'a_get_first_product_only': self.get_first_product_only,
'a_ids_product': self.ids_product,
'a_get_all_permutation': self.get_all_permutation,
'a_get_inactive_permutation': self.get_inactive_permutation,
# 'a_get_first_permutation_only': self.get_first_permutation_only,
'a_ids_permutation': self.ids_permutation,
'a_get_all_image': self.get_all_image,
'a_get_inactive_image': self.get_inactive_image,
# 'a_get_first_image_only': self.get_first_image_only,
'a_ids_image': self.ids_image,
# 'a_get_all_delivery_region': self.get_all_region,
# 'a_get_inactive_delivery_region': self.get_inactive_region,
# 'a_get_first_delivery_region_only': self.get_first_region_only,
# 'a_ids_delivery_region': self.ids_region,
# 'a_get_all_currency': self.get_all_currency,
# 'a_get_inactive_currency': self.get_inactive_currency,
# 'a_get_first_currency_only': self.get_first_currency_only,
# 'a_ids_currency': self.ids_currency,
# 'a_get_all_discount': self.get_all_discount,
# 'a_get_inactive_discount': self.get_inactive_discount,
# 'a_ids_discount': self.ids_discount,
'a_get_products_quantity_stock_below_min': self.get_products_quantity_stock_below_min
}
@staticmethod
def from_form_filters_product(form, id_user):
# if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product)
has_filter_category = not (form.id_category.data == '0' or form.id_category.data == '')
is_not_empty = av.input_bool(form.is_not_empty.data, "is_not_empty", "Parameters_Product.from_form_filters_product")
active = av.input_bool(form.active.data, "active", "Parameters_Product.from_form_filters_product")
return Parameters_Product(
a_id_user = id_user,
get_all_product_category = not has_filter_category,
get_inactive_product_category = not active,
# get_first_product_category_only = False,
ids_product_category = str(form.id_category.data),
get_all_product = True,
get_inactive_product = not active,
# get_first_product_only = False,
ids_product = '',
get_all_permutation = True,
get_inactive_permutation = not active,
# get_first_permutation_only = False,
ids_permutation = '',
get_all_image = False,
get_inactive_image = False,
# get_first_image_only = False,
ids_image = '',
# get_all_region = False,
# get_inactive_region = False,
# get_first_region_only = False,
# ids_region = '',
# get_all_currency = False,
# get_inactive_currency = False,
# get_first_currency_only = False,
# ids_currency = '',
# get_all_discount = False,
# get_inactive_discount = False,
# ids_discount = '',
get_products_quantity_stock_below_min = False
)
@staticmethod
def from_form_filters_product_permutation(form):
# if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
# av.val_instance(form, 'form', 'Parameters_Product.from_form', Form_Base)
has_category_filter = not (form.id_category.data is None or form.id_category.data == '0' or form.id_category.data == '')
has_product_filter = not (form.id_product.data is None or form.id_product.data == '0' or form.id_product.data == '')
get_permutations_stock_below_min = av.input_bool(form.is_out_of_stock.data, "is_out_of_stock", "Parameters_Product.from_form")
Helper_App.console_log(f'form question: {type(form.is_out_of_stock)}\nbool interpretted: {get_permutations_stock_below_min}\type form: {type(form)}')
return Parameters_Product(
get_all_product_category = not has_category_filter,
get_inactive_product_category = False,
# get_first_product_category_only = False,
ids_product_category = str(form.id_category.data) if has_category_filter else '',
get_all_product = not has_product_filter,
get_inactive_product = False,
# get_first_product_only = False,
ids_product = str(form.id_product.data) if has_product_filter else '',
get_all_permutation = not get_permutations_stock_below_min,
get_inactive_permutation = False,
# get_first_permutation_only = False,
ids_permutation = '',
get_all_image = False,
get_inactive_image = False,
# get_first_image_only = False,
ids_image = '',
# get_all_region = False,
# get_inactive_region = False,
# get_first_region_only = False,
# ids_region = '',
# get_all_currency = False,
# get_inactive_currency = False,
# get_first_currency_only = False,
# ids_currency = '',
# get_all_discount = False,
# get_inactive_discount = False,
# ids_discount = '',
get_products_quantity_stock_below_min = get_permutations_stock_below_min
)
@classmethod
def get_default(cls, id_user):
return cls(
a_id_user = id_user,
get_all_product_category = True,
get_inactive_product_category = False,
# get_first_product_category_only = False,
ids_product_category = '',
get_all_product = True,
get_inactive_product = False,
# get_first_product_only = False,
ids_product = '',
get_all_permutation = True,
get_inactive_permutation = False,
# get_first_permutation_only = False,
ids_permutation = '',
get_all_image = True,
get_inactive_image = False,
# get_first_image_only = False,
ids_image = '',
# get_all_region = True,
# et_inactive_region = False,
# get_first_region_only = False,
# ids_region = '',
# get_all_currency = True,
# get_inactive_currency = False,
# get_first_currency_only = False,
# ids_currency = '',
# get_all_discount = True,
# get_inactive_discount = False,
# ids_discount = '',
get_products_quantity_stock_below_min = True
)
@classmethod
def from_json(cls, json):
return cls(
get_all_product_category = json.get('a_get_all_product_category', False),
get_inactive_product_category = json.get('a_get_inactive_product_category', False),
# get_first_product_category_only = json.get('a_get_first_product_category_only', False),
ids_product_category = json.get('a_ids_product_category', ''),
get_all_product = json.get('a_get_all_product', False),
get_inactive_product = json.get('a_get_inactive_product', False),
# get_first_product_only = json.get('a_get_first_product_only', False),
ids_product = json.get('a_ids_product', ''),
get_all_permutation = json.get('a_get_all_permutation', False),
get_inactive_permutation = json.get('a_get_inactive_permutation', False),
# get_first_permutation_only = json.get('a_get_first_permutation_only', False),
ids_permutation = json.get('a_ids_permutation', ''),
get_all_image = json.get('a_get_all_image', False),
get_inactive_image = json.get('a_get_inactive_image', False),
# get_first_image_only = json.get('a_get_first_image_only', False),
ids_image = json.get('a_ids_image', ''),
# get_all_region = json.get('a_get_all_region', False),
# get_inactive_region = json.get('a_get_inactive_region', False),
# get_first_region_only = json.get('a_get_first_region_only', False),
# ids_region = json.get('a_ids_region', ''),
# get_all_currency = json.get('a_get_all_currency', False),
# get_inactive_currency = json.get('a_get_inactive_currency', False),
# get_first_currency_only = json.get('a_get_first_currency_only', False),
# ids_currency = json.get('a_ids_currency', ''),
# get_all_discount = json.get('a_get_all_discount', False),
# get_inactive_discount = json.get('a_get_inactive_discount', False),
# ids_discount = json.get('a_ids_discount', ''),
get_products_quantity_stock_below_min = json.get('a_get_products_quantity_stock_below_min', False)
)
@classmethod
def from_filters_product_category(cls, filters_category):
return cls(
get_all_product_category = True,
get_inactive_product_category = filters_category.active.data,
ids_product_category = '',
get_all_product = True,
get_inactive_product = False,
ids_product = '',
get_all_permutation = True,
get_inactive_permutation = False,
ids_permutation = '',
get_all_image = False,
get_inactive_image = False,
ids_image = '',
get_products_quantity_stock_below_min = False
)
@classmethod
def from_filters_stock_item(cls, filters_stock_item):
return cls.from_form_filters_product_permutation(filters_stock_item)
"""
class Product_Temp(db.Model, Store_Base):
__tablename__ = 'Shop_Product_Temp'
__table_args__ = { 'extend_existing': True }
@@ -883,11 +412,6 @@ class Product_Temp(db.Model, Store_Base):
row.id_access_level_required = product.id_access_level_required[0] if isinstance(product.id_access_level_required, tuple) else product.id_access_level_required
row.active = product.active
row.display_order = product.display_order
"""
row.guid = product.guid
row.created_on = product.created_on
row.created_by = product.created_by
"""
return row
def to_json(self):
return {
@@ -900,10 +424,6 @@ class Product_Temp(db.Model, Store_Base):
'display_order': self.display_order,
'guid': self.guid,
}
"""
'created_on': self.created_on,
'created_by': self.created_by
"""
def __repr__(self):
return f'''Product_Temp
id_product: {self.id_product}

View File

@@ -463,19 +463,6 @@ class Product_Category_Container(Store_Base):
return ','.join(list_ids)
"""
class Table_Shop_Product_Category(db.Model):
__tablename__ = 'Shop_Product_Category'
id_category: int = db.Column(db.Integer, primary_key=True)
code: str = db.Column(db.String(50))
name: str = db.Column(db.String(255))
description: str = db.Column(db.String(4000))
active: bool = db.Column(db.Boolean)
display_order: int = db.Column(db.Integer)
created_on: datetime = db.Column(db.DateTime)
created_by: int = db.Column(db.Integer)
id_change_set: int = db.Column(db.Integer)
"""
class Product_Category_Temp(db.Model, Store_Base):
__tablename__ = 'Shop_Product_Category_Temp'
__table_args__ = { 'extend_existing': True }
@@ -488,11 +475,11 @@ class Product_Category_Temp(db.Model, Store_Base):
active: bool = db.Column(db.Boolean)
display_order: int = db.Column(db.Integer)
guid: str = db.Column(db.String(36))
# created_on: datetime = db.Column(db.DateTime)
# created_by: int = db.Column(db.Integer)
def __init__(self):
super().__init__()
self.id_temp = None
@classmethod
def from_product_category(cls, product_category):
row = cls()
@@ -503,12 +490,8 @@ class Product_Category_Temp(db.Model, Store_Base):
row.id_access_level_required = product_category.id_access_level_required[0] if isinstance(product_category.id_access_level_required, tuple) else product_category.id_access_level_required
row.active = product_category.active
row.display_order = product_category.display_order
"""
row.guid = product_category.guid
row.created_on = product_category.created_on
row.created_by = product_category.created_by
"""
return row
def to_json(self):
return {
'id_category': self.id_category,
@@ -520,10 +503,6 @@ class Product_Category_Temp(db.Model, Store_Base):
'display_order': self.display_order,
'guid': self.guid,
}
"""
'created_on': self.created_on,
'created_by': self.created_by
"""
def __repr__(self):
return str(self.__dict__)

View File

@@ -145,38 +145,6 @@ class Parameters_Product_Variation(Get_Many_Parameters_Base):
parameters.a_get_inactive_variation = get_inactive
return parameters
"""
class Product_Variation_Container(BaseModel):
variation_types: list = []
variations: list = []
def add_product_variation_type(self, variation_type):
av.val_instance(variation_type, 'variation_type', 'Product_Variation_Container.add_product_variation_type', Product_Variation_Type)
self.variations.append(variation_type)
def add_product_variation(self, variation):
av.val_instance(variation, 'variation', 'Product_Variation_Container.add_product_variation', Product_Variation)
if variation.variation_type is None:
variation_type = next(filterfalse(lambda x: x.id_type != variation.id_type, self.variation_types), None)
if variation_type is not None:
variation.variation_type = variation_type
self.variations.append(variation)
def __repr__(self):
return f'Product_Variation_Container:\nvariations_types: {self.variation_types}\nvariations: {self.variations}'
def to_list_variation_options(self):
list_variations = []
for variation in self.variations:
list_variations.append(variation.to_json_option())
Helper_App.console_log(f'list_variations: {list_variations}')
return list_variations
def to_list_variation_type_options(self):
list_variation_types = []
for variation_type in self.variation_types:
list_variation_types.append(variation_type.to_json_option())
return list_variation_types
"""
class Product_Variation_Temp(db.Model, Store_Base):
__tablename__ = 'Shop_Variation_Temp'
__table_args__ = { 'extend_existing': True }

View File

@@ -123,18 +123,6 @@ class Product_Variation_Tree():
at_leaf_node = node.is_leaf()
types.append(node.variation_type)
return types
"""
def get_product_variations(self):
variations = []
node = self.node_root
at_leaf_node = node.is_leaf()
variations.append(node.variation)
while not at_leaf_node:
node = node.nodes_child[0]
at_leaf_node = node.is_leaf()
variations.append(node.variation)
return variations
"""
def to_preview_str(self):
Helper_App.console_log(f'Product_Variation_Tree.to_preview_str')
variation_types = self.get_product_variation_types()

View File

@@ -107,18 +107,6 @@ class Product_Variation_Type(db.Model, Store_Base):
'value': self.id_type,
'text': self.name_singular
}
"""
def get_preview_variations(self):
preview = ''
if len(self.variations) > 0:
# preview = '\n'.join([variation.name for variation in self.variations])
preview = '<p>' + '</p><p>'.join([variation.name for variation in self.variations]) + '</p>'
return preview
def get_str_list_ids_variation(self):
if self.variations is None or len(self.variations) == 0:
return ''
return ','.join([str(variation.id_variation) for variation in self.variations])
"""
class Product_Variation_Type_Temp(db.Model, Store_Base):
__tablename__ = 'Shop_Variation_Type_Temp'

View File

@@ -56,12 +56,6 @@ class Stock_Item(db.Model, Store_Base):
is_consumed = db.Column(db.Boolean)
date_consumed = db.Column(db.DateTime)
active = db.Column(db.Boolean)
"""
can_view = db.Column(db.Boolean)
can_edit = db.Column(db.Boolean)
can_admin = db.Column(db.Boolean)
"""
# variation_tree: Product_Variation_Tree = None
def __init__(self):
super().__init__()
@@ -93,11 +87,6 @@ class Stock_Item(db.Model, Store_Base):
stock_item.is_consumed = av.input_bool(query_row[22], "is_consumed", _m, v_arg_type=v_arg_type)
stock_item.date_consumed = query_row[23]
stock_item.active = av.input_bool(query_row[24], "active", _m, v_arg_type=v_arg_type)
"""
stock_item.can_view = av.input_bool(query_row[24], "can_view", _m, v_arg_type=v_arg_type)
stock_item.can_edit = av.input_bool(query_row[25], "can_edit", _m, v_arg_type=v_arg_type)
stock_item.can_admin = av.input_bool(query_row[26], "can_admin", _m, v_arg_type=v_arg_type)
"""
return stock_item
@classmethod
@@ -163,18 +152,6 @@ class Stock_Item(db.Model, Store_Base):
if permutation.is_available():
return True
return False
"""
def to_permutation_row_list(self):
list_rows = []
for permutation in self.permutations:
list_rows.append(permutation.to_row_permutation())
return list_rows
def to_json_option(self):
return {
'value': self.id_stock_item,
'text': self.id_stock_item
}
"""
class Parameters_Stock_Item(Get_Many_Parameters_Base):
a_get_all_product_permutation: bool

View File

@@ -18,43 +18,6 @@ import lib.argument_validation as av
# external
from typing import ClassVar
"""
class I_Store_Base():
@abstractmethod
def __repr__(self):
pass
@classmethod
@abstractmethod
def from_json(cls, json):
pass
@abstractmethod
def to_json(self):
pass
@abstractmethod
def to_json_option(self):
pass
@abstractmethod
def test_69 (self):
pass
""
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
for name, value in vars(Store_Base).items():
if getattr(value, "__isabstractmethod__", False):
if name not in cls.__dict__:
raise TypeError(f"Can't instantiate class {cls.__name__} "
f"without implementation of abstract method {name}")
subclass_value = cls.__dict__[name]
if (isinstance(value, (staticmethod, classmethod)) and
not isinstance(subclass_value, type(value))):
raise TypeError(f"Abstract {type(value).__name__} {name} in {cls.__name__} "
f"must be implemented as a {type(value).__name__}")
def __new__(cls, *args, **kwargs):
if cls is Store_Base:
raise TypeError("Can't instantiate abstract class Store_Base directly")
return super().__new__(cls)
""
"""
class Store_Base(Base):
# ATTR_ID_CURRENCY_COST: ClassVar[str] = 'id_currency_cost'
@@ -124,6 +87,10 @@ class Store_Base(Base):
FLAG_UNIT_MEASUREMENT_LATENCY_MANUFACTURE: ClassVar[str] = 'unit_measurement_latency_manufacture'
FLAG_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = 'unit_measurement_quantity'
FLAG_VALUE_TEXT: ClassVar[str] = 'value_text'
KEY_BASKET: ClassVar[str] = 'basket'
KEY_IS_INCLUDED_VAT: ClassVar[str] = 'is-included_vat'
KEY_ID_CURRENCY: ClassVar[str] = 'currency'
KEY_ID_REGION_DELIVERY: ClassVar[str] = 'id-region-delivery'
def __repr__(self):
return str(self.__dict__)

View File

@@ -1,161 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Stripe Business Object
Description:
Business objects for Stripe
"""
# internal
import lib.argument_validation as av
from lib import data_types
from forms.forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
from extensions import db
from helpers.helper_app import Helper_App
# external
from datetime import datetime, timedelta
import locale
class Stripe_Product(db.Model):
id_product = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
description = db.Column(db.String(4000))
price_GBP_full = db.Column(db.Float)
id_category = db.Column(db.Integer)
lead_time_manuf = db.Column(db.Integer)
quantity_min = db.Column(db.Float)
quantity_max = db.Column(db.Float)
quantity_step = db.Column(db.Float)
quantity_stock = db.Column(db.Float)
id_stripe_product = db.Column(db.String(255))
id_stripe_price = db.Column(db.String(255))
is_subscription = db.Column(db.Boolean)
name_recurring_interval = db.Column(db.String(255))
name_plural_recurring_interval = db.Column(db.String(256))
count_recurring_interval = db.Column(db.Integer)
display_order = db.Column(db.Integer)
can_view = db.Column(db.Boolean)
can_edit = db.Column(db.Boolean)
can_admin = db.Column(db.Boolean)
# form_basket_add: Form_Basket_Add
# form_basket_edit: Form_Basket_Edit
def __new__(cls, id, name, description, price_GBP_full, id_category, lead_time_manuf, quantity_min, quantity_max, quantity_step, quantity_stock, id_stripe_product, id_stripe_price,
is_subscription, name_recurring_interval, name_plural_recurring_interval, count_recurring_interval, display_order, can_view, can_edit, can_admin):
_m = 'Product.__new__'
v_arg_type = 'class attribute'
av.val_int(id, 'id', _m, 0, v_arg_type=v_arg_type)
av.val_str(name, 'name', _m, max_len=256, v_arg_type=v_arg_type)
av.val_str(description, 'description', _m, max_len=4000, v_arg_type=v_arg_type)
av.full_val_float(price_GBP_full, 'price_GBP_full', _m, 0., v_arg_type=v_arg_type)
av.val_int(id_category, 'id_category', _m, 0, v_arg_type=v_arg_type)
av.val_int(lead_time_manuf, 'lead_time_manuf', _m, 0, v_arg_type=v_arg_type)
av.full_val_float(quantity_step, 'quantity_step', _m, 0., v_arg_type=v_arg_type)
av.full_val_float(quantity_min, 'quantity_min', _m, quantity_step, v_arg_type=v_arg_type)
av.full_val_float(quantity_max, 'quantity_max', _m, quantity_min, v_arg_type=v_arg_type)
av.full_val_float(quantity_stock, 'quantity_stock', _m, 0, v_arg_type=v_arg_type)
av.val_str(id_stripe_product, 'id_stripe_product', _m, max_len=100, v_arg_type=v_arg_type)
av.val_str(id_stripe_price, 'id_stripe_price', _m, max_len=100, v_arg_type=v_arg_type)
av.full_val_bool(is_subscription, 'is_subscription', _m, v_arg_type=v_arg_type)
Helper_App.console_log(f'is_subscription: {is_subscription}, {av.input_bool(is_subscription, "is_subscription", _m, v_arg_type=v_arg_type)}')
is_subscription = av.input_bool(is_subscription, "is_subscription", _m, v_arg_type=v_arg_type)
if is_subscription:
av.val_str(name_recurring_interval, 'name_recurring_interval', _m, max_len=255, v_arg_type=v_arg_type)
av.val_str(name_plural_recurring_interval, 'name_plural_recurring_interval', _m, max_len=256, v_arg_type=v_arg_type)
av.val_int(count_recurring_interval, 'count_recurring_interval', _m, 0, v_arg_type=v_arg_type)
av.val_int(display_order, 'display_order', _m, v_arg_type=v_arg_type)
av.full_val_bool(can_view, 'can_view', _m, v_arg_type=v_arg_type)
# can_view = av.input_bool(can_view, "can_view", _m, v_arg_type=v_arg_type)
av.full_val_bool(can_edit, 'can_edit', _m, v_arg_type=v_arg_type)
# can_edit = av.input_bool(can_edit, "can_edit", _m, v_arg_type=v_arg_type)
av.full_val_bool(can_admin, 'can_admin', _m, v_arg_type=v_arg_type)
# can_admin = av.input_bool(can_admin, "can_admin", _m, v_arg_type=v_arg_type)
return super(Product, cls).__new__(cls) # , id, name, description, price_GBP, id_category, lead_time_manuf, quantity_min, quantity_max, quantity_step, quantity_stock, id_stripe_product, id_stripe_price,
# is_subscription, name_recurring_interval, name_plural_recurring_interval, count_recurring_interval, can_view, can_edit, can_admin)
def __init__(self, id, name, description, price_GBP_full, id_category, lead_time_manuf, quantity_min, quantity_max, quantity_step, quantity_stock, id_stripe_product, id_stripe_price,
is_subscription, name_recurring_interval, name_plural_recurring_interval, count_recurring_interval, display_order, can_view, can_edit, can_admin):
_m = 'Product.__new__'
v_arg_type = 'class attribute'
self.id_product = id
self.name = name
self.description = description
self.price_GBP_full = price_GBP_full
self.id_category = id_category
self.lead_time_manuf = lead_time_manuf
self.quantity_min = quantity_min
self.quantity_max = quantity_max
self.quantity_step = quantity_step
self.quantity_stock = quantity_stock
self.id_stripe_product = id_stripe_product
self.id_stripe_price = id_stripe_price
self.is_subscription = av.input_bool(is_subscription, "is_subscription", _m, v_arg_type=v_arg_type)
self.name_recurring_interval = name_recurring_interval
self.name_plural_recurring_interval = name_plural_recurring_interval
self.count_recurring_interval = count_recurring_interval
self.display_order = display_order
self.can_view = av.input_bool(can_view, "can_view", _m, v_arg_type=v_arg_type)
self.can_edit = av.input_bool(can_edit, "can_edit", _m, v_arg_type=v_arg_type)
self.can_admin = av.input_bool(can_admin, "can_admin", _m, v_arg_type=v_arg_type)
self.variations = []
self.images = []
self.delivery_options = []
self.discounts = []
self.discount_index = {}
super().__init__()
self.form_basket_add = Form_Basket_Add()
self.form_basket_edit = Form_Basket_Edit()
def output_lead_time(self):
return '1 day' if self.lead_time_manuf == 1 else f'{self.lead_time_manuf} days'
def output_delivery_date(self):
return (datetime.now() + timedelta(days=self.lead_time_manuf)).strftime('%A, %d %B %Y')
def output_price(self):
locale.setlocale(locale.LC_ALL, '')
return locale.format_string("%d", self.price_GBP_full, grouping=True)
"""
def add_form_basket_add(self):
self.form_basket_add = None
def add_form_basket_edit(self):
self.form_basket_edit = None
"""
def __repr__(self):
return f'''Product
id: {self.id_product}
name: {self.name}
description: {self.description}
price_GBP_full: {self.price_GBP_full}
id_category: {self.id_category}
lead_time_manuf: {self.lead_time_manuf}
quantity_min: {self.quantity_min}
quantity_max: {self.quantity_max}
quantity_step: {self.quantity_step}
quantity_stock: {self.quantity_stock}
id_stripe_product: {self.id_stripe_product}
id_stripe_price: {self.id_stripe_price}
is_subscription: {self.is_subscription}
name_recurring_interval: {self.name_recurring_interval}
name_plural_recurring_interval: {self.name_plural_recurring_interval}
count_recurring_interval: {self.count_recurring_interval}
display_order: {self.display_order}
can_view: {self.can_view}
can_edit: {self.can_edit}
can_admin: {self.can_admin}
variations: {self.variations}
images: {self.images}
delivery_options: {self.delivery_options}
'''
def add_product_price_discount(self, discount):
_m = 'Category.add_product'
av.val_instance(discount, 'discount', _m, Discount)
# self.product_index.append(len(self.products))
self.discount_index[discount.id_discount] = len(self.discounts)
self.discounts.append(discount)

View File

@@ -185,48 +185,6 @@ class Parameters_User(Get_Many_Parameters_Base):
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)

104
config.py
View File

@@ -10,7 +10,6 @@ Description:
Configuration variables
"""
# IMPORTS
from lib import argument_validation as av
import os
from dotenv import load_dotenv, find_dotenv
@@ -18,17 +17,35 @@ from flask import current_app
load_dotenv(find_dotenv())
# CLASSES
class Config:
is_development = False
is_production = False
# Miscellaneous
DEBUG = False # av.input_bool(os.getenv('DEBUG'), 'DEBUG', 'Config')
TESTING = False
URL_HOST = os.getenv('URL_HOST')
SECRET_KEY = os.getenv('KEY_SECRET_FLASK') # gen cmd: openssl rand -hex 32
# Add other configuration variables as needed
# MySQL
DB_HOST = os.getenv('DB_HOST')
DB_NAME = os.getenv('partsltd_prod')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_USER = os.getenv('DB_USER')
DEBUG = False
DOMAIN_AUTH0 = os.getenv('DOMAIN_AUTH0')
ID_AUTH0_CLIENT = os.getenv('ID_AUTH0_CLIENT')
ID_AUTH0_CLIENT_SECRET = os.getenv('ID_AUTH0_CLIENT_SECRET')
ID_TOKEN_USER = 'user'
MAIL_DEBUG = False
MAIL_SERVER = 'mail.partsltd.co.uk'
MAIL_PORT = 465
MAIL_USE_TLS = False
MAIL_USE_SSL = True
MAIL_USERNAME = os.getenv('MAIL_DEFAULT_SENDER')
MAIL_PASSWORD = os.getenv('MAIL_PASSWORD')
MAIL_DEFAULT_SENDER = os.getenv('MAIL_DEFAULT_SENDER')
MAIL_CONTACT_PUBLIC = os.getenv('MAIL_CONTACT_PUBLIC')
RECAPTCHA_PUBLIC_KEY = os.getenv('RECAPTCHA_PUBLIC_KEY')
RECAPTCHA_PRIVATE_KEY = os.getenv('RECAPTCHA_PRIVATE_KEY')
REMEMBER_COOKIE_SECURE = True
SECRET_KEY = os.getenv('KEY_SECRET_FLASK')
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax' # 'Strict' # Strict is preferable for security, but Lax is required for OAuth functionality
SQLALCHEMY_DATABASE_URI = os.getenv('SQLALCHEMY_DATABASE_URI')
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ENGINE_OPTIONS = {
@@ -37,91 +54,28 @@ class Config:
'pool_pre_ping': True,
'pool_timeout': 30,
}
# Auth0
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax' # 'Strict' # Strict is preferable for security, but Lax is required for OAuth functionality
REMEMBER_COOKIE_SECURE = True
# PERMANENT_SESSION_LIFETIME = 3600
TESTING = False
URL_HOST = os.getenv('URL_HOST')
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
WTF_CSRF_SSL_STRICT = False
WTF_CSRF_TIME_LIMIT = None
WTF_CSRF_SSL_STRICT = False # Allows testing without HTTPS
ID_AUTH0_CLIENT = os.getenv('ID_AUTH0_CLIENT')
ID_AUTH0_CLIENT_SECRET = os.getenv('ID_AUTH0_CLIENT_SECRET')
DOMAIN_AUTH0 = os.getenv('DOMAIN_AUTH0')
ID_TOKEN_USER = 'user'
# PostgreSQL
DB_NAME = os.getenv('partsltd')
DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_HOST = os.getenv('DB_HOST')
# DB_PORT = os.getenv('DB_PORT')
# Store
# is_included_VAT = True
"""
KEY_IS_INCLUDED_VAT = 'is_included_VAT'
code_currency = 1
KEY_CODE_CURRENCY = 'id_currency'
code_region_delivery = 1
KEY_CODE_REGION_DELIVERY = 'id_region_delivery'
KEY_ID_CURRENCY = 'id_currency'
KEY_ID_REGION_DELIVERY = 'id_region_delivery'
"""
# id_currency = 1
# id_region_delivery = 1
# Mail
MAIL_DEBUG = False # av.input_bool(os.getenv('DEBUG'), 'DEBUG', 'Config')
MAIL_SERVER = 'mail.partsltd.co.uk' # 'smtp.gmail.com'
MAIL_PORT = 465 # 587
MAIL_USE_TLS = False
MAIL_USE_SSL = True
MAIL_USERNAME = os.getenv('MAIL_DEFAULT_SENDER')
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')
class DevelopmentConfig(Config):
is_development = True
# Add development-specific configuration variables
DEBUG = True
MAIL_DEBUG = True
SESSION_COOKIE_SECURE = False
class ProductionConfig(Config):
is_production = True
# Add production-specific configuration variables
pass
# Set the configuration class based on the environment
# You can change 'development' to 'production' when deploying
config_env = os.getenv('FLASK_ENV', "production")
with open('app.log', 'a') as f:
print(f'config_env: {config_env}')
f.write(f'config_env: {config_env}\n')
# current_app.logger.error(f'config_env: {config_env}') # logger not yet initialised
if config_env == 'development':
app_config = DevelopmentConfig
elif config_env == 'production':
app_config = ProductionConfig
else:
raise ValueError("Invalid configuration environment")
# environment variables
"""
SET KEY_SECRET_FLASK=nips
SET ID_AUTH0_CLIENT=
SET ID_AUTH0_CLIENT_SECRET=
SET DOMAIN_AUTH0=
SET MAIL_PASSWORD=
SET RECAPTCHA_PUBLIC_KEY=
SET RECAPTCHA_PRIVATE_KEY=
SET SQLALCHEMY_DATABASE_URI=
SET URL_HOST=
"""
# SET SQLALCHEMY_DATABASE_URI = mysql://username:password@localhost/dbname
# Replace 'username', 'password', 'localhost', and 'dbname' with your actual database credentials

View File

@@ -59,18 +59,15 @@ 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
# CC = form.CC.data # not in use
name = form.name.data
message = form.message.data
# send email
mailItem = Message("PARTS Website Contact Us Message", recipients=[current_app.config['MAIL_CONTACT_PUBLIC']])
mailItem.body = f"Dear Lord Edward Middleton-Smith,\n\n{message}\n\nKind regards,\n{name}\n{email}"
mail.send(mailItem)
return "Submitted."
return "Invalid. Failed to submit."
# html_body = render_template('pages/core/_contact.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
@@ -88,7 +85,6 @@ def admin_home():
try:
model = Model_View_Admin_Home()
if not model.is_user_logged_in:
# return redirect(url_for('routes_user.login', callback = Model_View_Admin_Home.HASH_PAGE_ADMIN_HOME))
return redirect(url_for('routes_core.home'))
if not (model.user.can_admin_store or model.user.can_admin_user):
return redirect(url_for('routes_core.home'))

View File

@@ -1,167 +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
from helpers.helper_app import Helper_App
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
# 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():
Helper_App.console_log(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
Helper_App.console_log(f"Success! Here is your starter subscription product id: {starter_subscription.id}")
Helper_App.console_log(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 == '':
Helper_App.console_log('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"))))
app = Flask(__name__, static_folder=static_dir,
static_url_path="", template_folder=static_dir)
@app.route('/', methods=['GET'])
def get_example():
# 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('../templates/_home.html')
@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')
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='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']
Helper_App.console_log('event ' + event_type)
if event_type == 'checkout.session.completed':
Helper_App.console_log('🔔 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

@@ -39,7 +39,6 @@ def products():
Helper_App.console_log(f'form_filters={form_filters}')
model = Model_View_Store_Product(form_filters)
if not model.is_user_logged_in:
# return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product.FLAG_CALLBACK: Model_View_Store_Product.HASH_PAGE_STORE_PRODUCTS })))
return redirect(url_for('routes_core.home'))
return render_template('pages/store/_products.html', model = model)
@@ -54,7 +53,6 @@ def save_product():
Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_FAILURE,
Model_View_Store_Product.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'
})
# filters_form = Filters_Product.from_form(form_filters)
Helper_App.console_log(f'form_filters: {form_filters}')
products = data[Model_View_Store_Product.FLAG_PRODUCT]
@@ -66,7 +64,6 @@ def save_product():
objsProduct = []
for product in products:
objsProduct.append(Product.from_json(product))
# model_save = Model_View_Store_Product() # filters_product=filters_form)
Helper_App.console_log(f'objsProduct={objsProduct}')
save_errors = Model_View_Store_Product.save_products(data.get('comment', 'No comment'), objsProduct)

View File

@@ -31,31 +31,14 @@ routes_store_product_category = Blueprint('routes_store_product_category', __nam
@routes_store_product_category.route(Model_View_Store_Product_Category.HASH_PAGE_STORE_PRODUCT_CATEGORIES, methods=['GET'])
def categories():
Helper_App.console_log('categories')
# data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Product_Category.from_json(request.args)
except Exception as e:
Helper_App.console_log(f'Error: {e}')
form_filters = Filters_Product_Category()
Helper_App.console_log(f'form_filters={form_filters}')
"""
filters = Filters_Product_Category.get_default()
have_changed_filters = False
arg_filter_is_not_empty = request.args.get(Model_View_Store_Product_Category.FLAG_IS_NOT_EMPTY, None)
have_changed_filters = have_changed_filters or arg_filter_is_not_empty is None
Helper_App.console_log(f'arg_filter_is_not_empty={arg_filter_is_not_empty}')
filters.is_not_empty = filters.is_not_empty if arg_filter_is_not_empty is None else av.input_bool(arg_filter_is_not_empty, 'is_not_empty', 'filter_category')
arg_filter_active = request.args.get(Model_View_Store_Product_Category.FLAG_ACTIVE, None)
have_changed_filters = have_changed_filters or arg_filter_active is None
Helper_App.console_log(f'arg_filter_active={arg_filter_active}')
filters.active = filters.active if arg_filter_active is None else av.input_bool(arg_filter_active, 'active', 'filter_category')
if have_changed_filters:
Helper_App.console_log('redirecting')
return redirect(url_for('routes_store_product_category.categories', **filters.to_json()))
"""
model = Model_View_Store_Product_Category(form_filters)
if not model.is_user_logged_in:
# return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product_Category.FLAG_CALLBACK: Model_View_Store_Product_Category.HASH_PAGE_STORE_PRODUCT_CATEGORIES })))
return redirect(url_for('routes_core.home'))
return render_template('pages/store/_product_categories.html', model = model)
@@ -69,7 +52,6 @@ def save_category():
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE,
Model_View_Store_Product_Category.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'
})
# filters_form = Filters_Product_Category.from_form(form_filters)
categories = data[Model_View_Store_Product_Category.FLAG_PRODUCT_CATEGORY]
if len(categories) == 0:
@@ -80,7 +62,6 @@ def save_category():
objsCategory = []
for category in categories:
objsCategory.append(Product_Category.from_json(category))
# model_save = Model_View_Store_Product_Category() # filters_product=filters_form)
Helper_App.console_log(f'objsCategory={objsCategory}')
errors = Model_View_Store_Product_Category.save_categories(data.get('comment', 'No comment'), objsCategory)

View File

@@ -34,7 +34,6 @@ routes_store_product_permutation = Blueprint('routes_store_product_permutation',
def permutations():
Helper_App.console_log('permutations')
data = request.args
# Helper_App.console_log(f'data={data}\nrequest.args={request.args}\nrequest.form={request.form}\nrequest.data={request.data}\nrequest.values={request.values}\nrequest.headers={request.headers}')
try:
form_filters = Filters_Product_Permutation.from_json(data)
except Exception as e:
@@ -43,7 +42,6 @@ def permutations():
Helper_App.console_log(f'form_filters={form_filters}')
model = Model_View_Store_Product_Permutation(form_filters)
if not model.is_user_logged_in:
# return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product_Permutation.FLAG_CALLBACK: Model_View_Store_Product_Permutation.HASH_PAGE_STORE_PRODUCT_PERMUTATIONS })))
return redirect(url_for('routes_core.home'))
return render_template('pages/store/_product_permutations.html', model = model)
@@ -58,7 +56,6 @@ def save_permutation():
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE,
Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'
})
# filters_form = Filters_Product_Permutation.from_form(form_filters)
Helper_App.console_log(f'form_filters: {form_filters}')
permutations = data[Model_View_Store_Product_Permutation.FLAG_PRODUCT_PERMUTATION]
@@ -70,7 +67,6 @@ def save_permutation():
objsPermutation = []
for permutation in permutations:
objsPermutation.append(Product_Permutation.from_json(permutation))
# model_save = Model_View_Store_Product_Permutation() # filters_product=filters_form)
Helper_App.console_log(f'objsPermutation={objsPermutation}')
Model_View_Store_Product_Permutation.save_permutations(data.get('comment', 'No comment'), objsPermutation)

View File

@@ -55,7 +55,6 @@ def save_product_variation():
Model_View_Store_Product_Variation.FLAG_STATUS: Model_View_Store_Product_Variation.FLAG_FAILURE,
Model_View_Store_Product_Variation.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'
})
# filters_form = Filters_Product_Variation.from_form(form_filters)
Helper_App.console_log(f'form_filters: {form_filters}')
product_variation_types = data[Model_View_Store_Product_Variation.FLAG_PRODUCT_VARIATION_TYPE]
@@ -67,7 +66,6 @@ def save_product_variation():
objs_product_variation_type = []
for product_variation_type in product_variation_types:
objs_product_variation_type.append(Product_Variation_Type.from_json(product_variation_type))
# model_save = Model_View_Store_Product_Variation() # filters_product_variation=filters_form)
Helper_App.console_log(f'objs_product_variation_type={objs_product_variation_type}')
save_errors = Model_View_Store_Product_Variation.save_product_variations(data.get('comment', 'No comment'), objs_product_variation_type)

View File

@@ -39,8 +39,6 @@ def stock_items():
Helper_App.console_log(f'form_filters={form_filters}')
model = Model_View_Store_Stock_Item(form_filters)
if not model.is_user_logged_in:
# return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Stock_Item.FLAG_CALLBACK: Model_View_Store_Stock_Item.HASH_PAGE_STORE_STOCK_ITEMS })))
# return requests.post(f"{current_app.config['URL_HOST']}{url_for('routes_user.login')}", json={ Model_View_Store_Stock_Item.FLAG_CALLBACK: Model_View_Store_Stock_Item.HASH_PAGE_STORE_STOCK_ITEMS })
return redirect(url_for('routes_core.home'))
return render_template('pages/store/_stock_items.html', model = model, datetime = datetime)
@@ -50,28 +48,6 @@ def save_stock_item():
data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Stock_Item.from_json(data[Model_View_Store_Stock_Item.FLAG_FORM_FILTERS])
"""
if not form_filters.validate_on_submit():
error_keys = list(form_filters.errors.keys())
try:
error_keys.remove(Stock_Item.ATTR_ID_PRODUCT_CATEGORY)
""
if not av.val_int(form_filters.id_product_category.data):
form_filters.errors[Stock_Item.ATTR_ID_PRODUCT_CATEGORY] = ['Invalid category.']
""
except:
pass
try:
error_keys.remove(Stock_Item.ATTR_ID_PRODUCT)
except:
pass
if error_keys:
return jsonify({
Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE,
Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'
})
"""
# filters_form = Filters_Stock_Item.from_form(form_filters)
Helper_App.console_log(f'form_filters: {form_filters}')
stock_items = data[Model_View_Store_Stock_Item.FLAG_STOCK_ITEM]
@@ -84,7 +60,6 @@ def save_stock_item():
objs_stock_item = []
for stock_item in stock_items:
objs_stock_item.append(Stock_Item.from_json(stock_item))
# model_save = Model_View_Store_Stock_Item() # filters_product=filters_form)
Helper_App.console_log(f'objs_stock_item={objs_stock_item}')
save_errors = Model_View_Store_Stock_Item.save_stock_items(data.get('comment', 'No comment'), objs_stock_item)
if len(save_errors) > 0:

View File

@@ -116,7 +116,7 @@ def login():
return jsonify({'status': 'error', 'message': str(e)}), 400
@routes_user.route("/login_callback") # <path:subpath>/<code>
@routes_user.route("/login_callback")
@handle_db_disconnect
def login_callback():
Helper_App.console_log('login_callback')
@@ -128,25 +128,13 @@ def login_callback():
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()
user = User.from_json_auth0(token)
Helper_App.console_log(f'user: {user}')
filters = Parameters_User.from_user(user)
datastore_user = DataStore_User()
@@ -168,13 +156,10 @@ def login_callback():
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')
hash_callback = state
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}")
@@ -188,38 +173,15 @@ def logout():
{
"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>
@routes_user.route("/logout_callback")
@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():
@@ -235,7 +197,6 @@ def user():
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:

View File

@@ -14,16 +14,6 @@ Datastore for Store
# from routes import bp_home
import lib.argument_validation as av
from business_objects.store.access_level import Access_Level
"""
from business_objects.store.basket import Basket, Basket_Item
from business_objects.store.product_category import Product_Category_Container, Product_Category
from business_objects.store.currency import Currency
from business_objects.store.image import Image
from business_objects.store.delivery_option import Delivery_Option
from business_objects.store.discount import Discount
from business_objects.store.order import Order
from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product # Permutation_Variation_Link
"""
from business_objects.region import Region
from business_objects.sql_error import SQL_Error
from business_objects.store.stock_item import Stock_Item
@@ -48,29 +38,11 @@ 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
@@ -78,9 +50,7 @@ class DataStore_Base(BaseModel):
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}('
if has_arguments:
arg_keys = list(argument_dict_list.keys())
@@ -90,15 +60,12 @@ 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:
result = db.session.execute(proc_string)
Helper_App.console_log(f'result: {result}')
# conn.session.remove()
return result
cursor = result.cursor
result_set_1 = cursor.fetchall()
@@ -200,7 +167,7 @@ class DataStore_Base(BaseModel):
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])
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}")
@@ -217,7 +184,6 @@ class DataStore_Base(BaseModel):
if db.session.dirty or db.session.new or db.session.deleted:
Helper_App.console_log("Session is not clean")
return
# Assuming `permanent_table_name` is a string representing the table name
table_object = db.metadata.tables.get(permanent_table_name)
if table_object is None:
Helper_App.console_log(f"Table {permanent_table_name} not found in metadata.")
@@ -225,30 +191,7 @@ 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):
@@ -269,7 +212,6 @@ class DataStore_Base(BaseModel):
time.sleep(wait_time)
retries += 1
# Ensure the session is clean for the retry
db.session.rollback()
except Exception as e:
db.session.rollback()
@@ -282,8 +224,6 @@ class DataStore_Base(BaseModel):
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)
@@ -304,7 +244,7 @@ class DataStore_Base(BaseModel):
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])
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}")
@@ -319,8 +259,6 @@ class DataStore_Base(BaseModel):
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)
@@ -341,7 +279,7 @@ class DataStore_Base(BaseModel):
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])
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}")
@@ -364,7 +302,6 @@ class DataStore_Base(BaseModel):
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
regions = []
for row in result_set_1:

View File

@@ -12,18 +12,16 @@ 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.store_base import Store_Base
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
@@ -44,30 +42,22 @@ 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
KEY_BASKET: ClassVar[str] = Store_Base.KEY_BASKET
KEY_IS_INCLUDED_VAT: ClassVar[str] = Store_Base.KEY_IS_INCLUDED_VAT
KEY_ID_CURRENCY: ClassVar[str] = Store_Base.KEY_ID_CURRENCY
KEY_ID_REGION_DELIVERY: ClassVar[str] = Store_Base.KEY_ID_REGION_DELIVERY
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
@@ -139,18 +129,11 @@ class DataStore_Store_Base(DataStore_Base):
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])
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}")
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:
@@ -172,18 +155,8 @@ class DataStore_Store_Base(DataStore_Base):
cursor.close()
Helper_App.console_log(f'get many category_list: {category_list}')
return category_list, errors # categories, category_index
return category_list, errors
"""
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 = []
@@ -210,7 +183,6 @@ class DataStore_Store_Base(DataStore_Base):
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
plants = []
for row in result_set_1:
@@ -236,7 +208,6 @@ class DataStore_Store_Base(DataStore_Base):
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
storage_locations = []
for row in result_set_1:
@@ -262,7 +233,6 @@ class DataStore_Store_Base(DataStore_Base):
cursor = result.cursor
Helper_App.console_log('data received')
# cursor.nextset()
result_set_1 = cursor.fetchall()
currencies = []
for row in result_set_1:
@@ -287,36 +257,22 @@ class DataStore_Store_Base(DataStore_Base):
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)
new_variation_type = Product_Variation_Type.from_DB_get_many_product_variation(row)
index_variation_type[new_variation_type.id_type] = len(variation_types)
variation_types.append(new_variation_type)
@@ -325,12 +281,9 @@ class DataStore_Store_Base(DataStore_Base):
# 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)
@@ -339,7 +292,7 @@ class DataStore_Store_Base(DataStore_Base):
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]
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}")

View File

@@ -1,143 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: DataStores
Feature: Store Basket DataStore
Description:
Datastore for Store Baskets
"""
# internal
# from routes import bp_home
import lib.argument_validation as av
from business_objects.store.basket import Basket, Basket_Item
from business_objects.sql_error import SQL_Error
from datastores.datastore_store_base import DataStore_Store_Base
from helpers.helper_app import Helper_App
# from helpers.helper_db_mysql import Helper_DB_MySQL
# from models.model_view_store_checkout import Model_View_Store_Checkout # circular!
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_Store_Basket(DataStore_Store_Base):
# Global constants
KEY_BASKET: ClassVar[str] = Basket.KEY_BASKET
# Attributes
def __init__(self, **kwargs):
super().__init__(**kwargs)
def get_metadata_basket(json_request):
try:
basket = json_request[DataStore_Store_Basket.KEY_BASKET]
except KeyError:
basket = {DataStore_Store_Basket.KEY_IS_INCLUDED_VAT: True, DataStore_Store_Basket.KEY_ID_CURRENCY: 1, DataStore_Store_Basket.KEY_ID_REGION_DELIVERY: 1}
is_included_VAT = basket[DataStore_Store_Basket.KEY_IS_INCLUDED_VAT]
id_currency = basket[DataStore_Store_Basket.KEY_ID_CURRENCY]
id_region_delivery = basket[DataStore_Store_Basket.KEY_ID_REGION_DELIVERY]
return id_currency, id_region_delivery, is_included_VAT
def edit_basket(self, ids_permutation_basket, quantities_permutation_basket, id_permutation_edit, quantity_permutation_edit, sum_not_edit, id_currency, id_region_delivery, is_included_VAT):
# redundant argument validation?
_m = 'DataStore_Store_Base.edit_basket'
Helper_App.console_log(f'{_m}\nstarting...')
# av.val_instance(filters, 'filters', _m, Parameters_Product_Category)
# av.val_str(ids_product_basket, 'ids_product_basket', _m)
av.val_str(ids_permutation_basket, 'ids_permutation_basket', _m)
# av.val_str(quantities_product_basket, 'quantities_product_basket', _m)
av.val_str(quantities_permutation_basket, 'quantities_permutation_basket', _m)
"""
if id_product_edit == 'None':
id_product_edit = None
else:
Helper_App.console_log(f'id_product_edit: {id_product_edit}')
av.val_int(id_product_edit, 'id_product_edit', _m)
"""
if id_permutation_edit == 'None' or str(type(id_permutation_edit)) =="<class 'NoneType'>":
id_permutation_edit = None
else:
Helper_App.console_log(f'id_permutation_edit: {id_permutation_edit}')
Helper_App.console_log(str(type(id_permutation_edit)))
av.val_int(id_permutation_edit, 'id_permutation_edit', _m)
if quantity_permutation_edit == 'None' or str(type(quantity_permutation_edit)) =="<class 'NoneType'>":
quantity_permutation_edit = None
else:
Helper_App.console_log(f'quantity_permutation_edit: {quantity_permutation_edit}')
av.val_int(quantity_permutation_edit, 'quantity_permutation_edit', _m)
if sum_not_edit == 'None':
sum_not_edit = None
else:
Helper_App.console_log(f'sum_not_edit: {sum_not_edit}')
av.val_bool(sum_not_edit, 'sum_not_edit', _m)
argument_dict_list = {
'a_id_user': self.info_user.get('sub'),
# 'a_ids_product_basket': ids_product_basket,
'a_ids_permutation_basket': ids_permutation_basket,
# 'a_quantities_product_basket': quantities_product_basket,
'a_quantities_permutation_basket': quantities_permutation_basket,
# 'a_id_product_edit': id_product_edit if id_permutation_edit is None else None,
'a_id_permutation_edit': id_permutation_edit,
'a_quantity_permutation_edit': quantity_permutation_edit,
'a_sum_not_edit': 1 if sum_not_edit else 0,
'a_id_currency': id_currency,
'a_id_region_purchase': id_region_delivery
}
result = self.db_procedure_execute('p_shop_edit_user_basket', argument_dict_list)
Helper_App.console_log('data received')
cursor = result.cursor
# categories, category_index = DataStore_Store_Base.input_many_product(cursor)
category_list, errors = DataStore_Store_Base.input_many_product(cursor)
Helper_App.console_log(f'cursor: {str(cursor)}')
# Basket
if not cursor.nextset():
raise Exception("No more query results! Cannot open basket contents")
result_set = cursor.fetchall()
Helper_App.console_log(f'raw basket: {result_set}')
# Helper_App.console_log(f'variations: {result_set_3}')
# variations = [Product_Variation(**row) for row in result_set_3]
basket = Basket(is_included_VAT, id_currency, id_region_delivery)
for row in result_set:
index_category = category_list.get_index_category_from_id(row[0])
category = category_list.categories[index_category]
index_product = category.get_index_product_from_id(row[1])
product = category.products[index_product]
basket_item = Basket_Item.from_product_and_quantity_and_VAT_included(product, row[7], self.app.is_included_VAT)
Helper_App.console_log(f'adding basket item: {row}')
Helper_App.console_log(f'basket item: {basket_item}')
basket.add_item(basket_item) # basket.append(basket_item) # Basket_Item(category.name, product, row[4]))
Helper_App.console_log(f'basket: {basket}')
# 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_Store_Base.db_cursor_clear(cursor)
return basket

View File

@@ -78,7 +78,7 @@ class DataStore_Store_Manufacturing_Purchase_Order(DataStore_Store_Base):
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])
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}")

View File

@@ -21,65 +21,7 @@ from helpers.helper_db_mysql import Helper_DB_MySQL
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 Table_Shop_Product_Category(db.Model):
__tablename__ = 'Shop_Product_Category'
id_category: int = db.Column(db.Integer, primary_key=True)
code: str = db.Column(db.String(50))
name: str = db.Column(db.String(255))
description: str = db.Column(db.String(4000))
active: bool = db.Column(db.Boolean)
display_order: int = db.Column(db.Integer)
created_on: datetime = db.Column(db.DateTime)
created_by: int = db.Column(db.Integer)
id_change_set: int = db.Column(db.Integer)
"""
"""
class Row_Shop_Product_Temp(db.Model):
__tablename__ = 'Shop_Product_Temp'
__table_args__ = { 'extend_existing': True }
id_product: int = db.Column(db.Integer, primary_key=True)
id_category: int = db.Column(db.Integer)
name: str = db.Column(db.String(50))
has_variations: str = db.Column(db.String(255))
id_access_level_required: int = db.Column(db.Integer)
active: bool = db.Column(db.Boolean)
display_order: int = db.Column(db.Integer)
guid: str = db.Column(db.BINARY(36))
@classmethod
def from_product(cls, product):
row = cls()
row.id_product = product.id_product[0] if isinstance(product.id_product, tuple) else product.id_product
row.id_category = product.id_category[0] if isinstance(product.id_category, tuple) else product.id_category
row.name = product.name[0] if isinstance(product.name, tuple) else product.name
row.id_access_level_required = product.id_access_level_required[0] if isinstance(product.id_access_level_required, tuple) else product.id_access_level_required
row.active = product.active
row.display_order = product.display_order
return row
def to_json(self):
return {
'id_product': self.id_product,
'id_category': self.id_category,
'name': self.name,
'has_variations': self.has_variations,
'id_access_level_required': self.id_access_level_required,
'active': av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'),
'display_order': self.display_order,
'guid': self.guid,
}
"""
class DataStore_Store_Product(DataStore_Store_Base):
def __init__(self):
@@ -115,16 +57,15 @@ class DataStore_Store_Product(DataStore_Store_Base):
}
save_result = cls.db_procedure_execute('p_shop_save_product', argument_dict_list)
cursor = save_result # .cursor
cursor = save_result
Helper_App.console_log('data received')
# 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])
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}")
try:

View File

@@ -40,8 +40,6 @@ class DataStore_Store_Product_Category(DataStore_Store_Base):
_m = 'DataStore_Store_Product_Category.save_categories'
Helper_App.console_log(f'{_m}\nstarting...')
Helper_App.console_log(f'comment: {comment}\ncategories: {categories}')
# av.val_str(comment, 'comment', _m)
# av.val_list_instances(categories, 'categories', _m, Product_Category, 1)
guid = Helper_DB_MySQL.create_guid()
now = datetime.now()
@@ -50,32 +48,15 @@ class DataStore_Store_Product_Category(DataStore_Store_Base):
id_category_new = 0
for category in categories:
row = Product_Category_Temp.from_product_category(category)
# row = category.to_temporary_record()
# id_tmp =
if row.id_category == '':
id_category_new -= 1
row.id_category = id_category_new
else:
Helper_App.console_log(f'row.id_category: {row.id_category}')
row.guid = guid
# row.created_on = now
# row.created_by = user.id_user
rows.append(row)
Helper_App.console_log(f'rows: {rows}')
"""
cursor = db.cursor()
Helper_App.console_log('cursor created')
cursor.executemany(
'INSERT INTO Shop_Product_Category_Temp (id_category, code, name, description, active, display_order, guid, created_on, created_by) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)',
categories
)
Helper_App.console_log('bulk upload executed')
db.commit()
Helper_App.console_log('bulk upload committed')
cursor.close()
Helper_App.console_log('cursor closed')
"""
DataStore_Store_Base.upload_bulk(Product_Category_Temp.__tablename__, rows, 1000)
argument_dict_list = {
@@ -92,7 +73,7 @@ class DataStore_Store_Product_Category(DataStore_Store_Base):
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])
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}")

View File

@@ -42,58 +42,17 @@ class DataStore_Store_Product_Permutation(DataStore_Store_Base):
def save_permutations(cls, comment, permutations):
_m = 'DataStore_Store_Product_Permutation.save_permutations'
av.val_str(comment, 'comment', _m)
# av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1)
guid = Helper_DB_MySQL.create_guid_str()
now = datetime.now()
user = cls.get_user_session()
rows = []
for permutation in permutations:
# row = permutation.to_temporary_record()
row = Product_Permutation_Temp.from_product_permutation(permutation)
row.guid = guid
rows.append(row)
Helper_App.console_log(f'rows: {rows}')
"""
cursor = db.cursor()
Helper_App.console_log('cursor created')
cursor.executemany(
'''INSERT INTO Shop_Product_Permutation_Temp (
id_permutation,
id_product,
description,
cost_local,
id_currency_cost,
profit_local_min,
latency_manufacture,
id_unit_measurement_quantity,
count_unit_measurement_quantity,
quantity_min,
quantity_max,
quantity_stock,
is_subscription,
id_unit_measurement_interval_recurrence,
count_interval_recurrence,
id_stripe_product,
does_expire_faster_once_unsealed,
id_unit_measurement_interval_expiration_unsealed,
count_interval_expiration_unsealed,
active,
guid
)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)''',
rows
)
Helper_App.console_log('cursor executed')
db.commit()
Helper_App.console_log('cursor committed')
cursor.close()
Helper_App.console_log('cursor closed')
"""
DataStore_Store_Base.upload_bulk(Product_Permutation_Temp.__tablename__, rows, 1000)
Helper_App.console_log('bulk uploaded')
argument_dict_list = {
'a_comment': comment,
@@ -103,4 +62,3 @@ class DataStore_Store_Product_Permutation(DataStore_Store_Base):
}
results = cls.db_procedure_execute('p_shop_save_product_permutation', argument_dict_list)
DataStore_Store_Base.db_cursor_clear(results.cursor)
Helper_App.console_log('saved product permutations')

View File

@@ -31,19 +31,12 @@ from pydantic import BaseModel, ConfigDict
from typing import ClassVar
from datetime import datetime
# db = SQLAlchemy()
class DataStore_Store_Stock_Item(DataStore_Store_Base):
# Global constants
# Attributes
def __init__(self):
super().__init__()
# Stock Items
def get_many_stock_item(self, parameters_stock_item, category_list):
# redundant argument validation?
_m = 'DataStore_Store_Stock_Item.get_many_stock_item'
av.val_instance(parameters_stock_item, 'parameters_stock_item', _m, Parameters_Stock_Item)
argument_dict = parameters_stock_item.to_json()
@@ -73,7 +66,7 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base):
Helper_App.console_log(f'raw categories: {result_set_1}')
for row in result_set_1:
new_stock_item = Stock_Item.from_DB_stock_item(row)
category_list.add_stock_item(new_stock_item) # , row)
category_list.add_stock_item(new_stock_item)
# Errors
cursor.nextset()
@@ -81,27 +74,11 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base):
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])
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}")
"""
if len(errors) > 0:
for error in errors:
if error.code == 'PRODUCT_AVAILABILITY':
ids_permutation_unavailable = DataStore_Store_Stock_Item.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_Stock_Item.db_cursor_clear(cursor)
return category_list, errors # categories, category_index
return category_list, errors
@classmethod
def save_stock_items(cls, comment, stock_items):
@@ -113,7 +90,6 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base):
user = cls.get_user_session()
rows = []
for stock_item in stock_items:
# row = permutation.to_temporary_record()
row = Stock_Item_Temp.from_stock_item(stock_item)
row.guid = guid
rows.append(row)
@@ -139,7 +115,7 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base):
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])
errors = [SQL_Error.from_DB_record(row) for row in result_set_e]
for error in errors:
Helper_App.console_log(f"Error [{error.code}]: {error.msg}")
DataStore_Store_Stock_Item.db_cursor_clear(cursor)

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

@@ -79,7 +79,7 @@ class DataStore_Store_Supplier(DataStore_Store_Base):
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])
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}")
@@ -135,7 +135,7 @@ class DataStore_Store_Supplier(DataStore_Store_Base):
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])
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}")

View File

@@ -79,7 +79,7 @@ class DataStore_Store_Supplier_Purchase_Order(DataStore_Store_Base):
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])
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}")

View File

@@ -37,16 +37,11 @@ db = SQLAlchemy()
class DataStore_User(DataStore_Store_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'),
@@ -66,7 +61,7 @@ class DataStore_User(DataStore_Store_Base):
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]
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}")
@@ -74,94 +69,28 @@ class DataStore_User(DataStore_Store_Base):
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:
@@ -170,13 +99,12 @@ class DataStore_User(DataStore_Store_Base):
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]
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}")
@@ -187,49 +115,25 @@ class DataStore_User(DataStore_Store_Base):
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:
@@ -238,13 +142,12 @@ class DataStore_User(DataStore_Store_Base):
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]
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}")

View File

@@ -21,15 +21,7 @@ class Form_Base_Meta(type(FlaskForm), ABCMeta):
class Form_Base(FlaskForm, metaclass=Form_Base_Meta):
"""
@classmethod
@abstractmethod
def from_filters(cls, filters):
pass
@abstractmethod
def __repr__(self):
pass
"""
def __repr__(self):
fields = ', '.join(
f"{name}={field.data}" for name, field in self._fields.items()
@@ -42,37 +34,9 @@ class Form_Base(FlaskForm, metaclass=Form_Base_Meta):
@classmethod
def get_default(cls):
return cls()
"""
@abstractmethod
def test_69(self):
pass
def get_Filters_Product_Category(data_request):
data_form = data_request[Model_View_Store_Product_Category.FLAG_FORM]
form_filters = Filters_Product_Category(**data_form)
form_filters.is_not_empty.data = av.input_bool(data_form['is_not_empty'], 'is_not_empty', 'filter_category')
form_filters.active.data = av.input_bool(data_form['active'], 'active', 'filter_category')
return form_filters
"""
@classmethod
def get_choices_blank(cls):
return [('', 'Select')]
@classmethod
def get_choice_all(cls):
return ('', 'All')
'''
class Filters_Stored_Procedure_Base(Form_Base):
"""
@abstractmethod
def __repr__(self):
pass
@classmethod
@abstractmethod
def from_json(cls, json):
pass
"""
@abstractmethod
def to_json(self):
pass
'''

View File

@@ -40,43 +40,24 @@ class Form_Register(FlaskForm):
submit = SubmitField('Submit')
"""
class Form_Product(FlaskForm): # for basket, product tiles, product add
# PositiveIntegerField with validation constraints
class Form_Basket_Add(FlaskForm):
quantity = IntegerField(
'Quantity',
validators=[
# InputRequired(message='Quantity'),
validators = [
NumberRange(min=1, message='Please enter a positive integer')
],
default=1
)
"""
class Form_Basket_Add(FlaskForm): # for basket, product tiles, product add
# PositiveIntegerField with validation constraints
quantity = IntegerField(
'Quantity',
validators=[
# InputRequired(message='Quantity'),
NumberRange(min=1, message='Please enter a positive integer')
],
default=1
# render_kw={'id-product': ''} # {Model_View_Store.attr_id_product: ''}
default = 1
)
submit = SubmitField('Add')
form_type = 'Form_Basket_Add'
class Form_Basket_Edit(FlaskForm): # for basket, product tiles, product add
# PositiveIntegerField with validation constraints
class Form_Basket_Edit(FlaskForm):
quantity = IntegerField(
'Quantity',
validators=[
# InputRequired(message='Quantity'),
validators = [
NumberRange(min=1, message='Please enter a positive integer')
],
default=1
# render_kw={'id-product': ''} # {Model_View_Store.attr_id_product: ''}
default = 1
)
submit = SubmitField('Update')
form_type = 'Form_Basket_Edit'
@@ -109,7 +90,6 @@ class Form_Currency(FlaskForm):
id_currency = SelectField('Currency', id='id_currency')
# Store
class Form_Supplier(FlaskForm):
id_id_supplier = 'id_supplier'
id_supplier = SelectField('Supplier', id='id_supplier')
@@ -124,11 +104,8 @@ class Form_Supplier(FlaskForm):
id_currency = SelectField('Currency ID')
is_active = BooleanField('Active', default = True)
# class Form_Supplier_Purchase_Order(FlaskForm):
# User
class Form_Filters_User(FlaskForm):
active = BooleanField('Active only?', default = True)
id_user = SelectField('User ID', validators=[Optional()], choices=[])

View File

@@ -28,14 +28,7 @@ from abc import ABCMeta, abstractmethod
class Filters_Product_Category(Form_Base):
is_not_empty = BooleanField('Not empty only?')
active = BooleanField("Active only?", default = True)
"""
@classmethod
def from_filters(cls, filters):
form = Filters_Product_Category()
form.is_not_empty.data = filters.is_not_empty
form.active.data = filters.active
return form
"""
def __repr__(self):
return f'Filters_Product_Category(is_not_empty={self.is_not_empty.data}, active={self.active.data})'
@classmethod

View File

@@ -32,18 +32,7 @@ class Filters_Product_Permutation(Form_Base):
active = BooleanField('Active only?', default=True)
quantity_min = FloatField('Min stock')
quantity_max = FloatField('Max stock')
# submit = SubmitField('Submit')
"""
@classmethod
def from_filters(cls, filters):
form = Filters_Product_Permutation()
form.id_category.choices = Store_Base.convert_list_objects_to_list_options(filters.categories)
form.id_product.choices = Store_Base.convert_list_objects_to_list_options(filters.products)
form.is_out_of_stock.data = filters.is_out_of_stock
form.quantity_min.data = filters.quantity_min
form.quantity_max.data = filters.quantity_max
return form
"""
def __repr__(self):
return f'''
Filters_Product_Permutation(

View File

@@ -31,24 +31,11 @@ class Filters_Stock_Item(Form_Base):
quantity_min = FloatField('Min stock')
quantity_max = FloatField('Max stock')
active = BooleanField("Active")
# submit = SubmitField('Submit')
"""
def __repr__(self):
return f'''
{self.__class__.__name__}(
id_category={self.id_category.data},
id_product={self.id_product.data},
is_out_of_stock={self.is_out_of_stock.data},
quantity_min={self.quantity_min.data},
quantity_max={self.quantity_max.data})
'''
"""
@classmethod
def from_json(cls, json):
form = cls()
# form.id_category.choices = [(json[Store_Base.ATTR_ID_PRODUCT_CATEGORY], json[Store_Base.ATTR_ID_PRODUCT_CATEGORY])]
form.id_category.data = json[Store_Base.ATTR_ID_PRODUCT_CATEGORY]
# form.id_product.choices = [(json[Store_Base.ATTR_ID_PRODUCT], json[Store_Base.ATTR_ID_PRODUCT])]
form.id_product.data = json[Store_Base.ATTR_ID_PRODUCT]
form.is_out_of_stock.data = av.input_bool(json[Store_Base.FLAG_IS_OUT_OF_STOCK], Store_Base.FLAG_IS_OUT_OF_STOCK, f'{cls.__name__}.from_json')
form.quantity_min.data = json[Store_Base.FLAG_QUANTITY_MIN]
@@ -69,11 +56,4 @@ class Filters_Stock_Item(Form_Base):
filters = cls()
filters.id_category.choices = cls.get_choices_blank()
filters.id_product.choices = cls.get_choices_blank()
"""
def import_values(self, form_filters):
self.id_category.data = form_filters.id_category.data
self.id_product.data = form_filters.id_product.data
self.is_out_of_stock.data = form_filters.is_out_of_stock.data
self.quantity_min.data = form_filters.quantity_min.data
self.quantity_max.data = form_filters.quantity_max.data
"""

View File

@@ -1,38 +0,0 @@
from abc import abstractmethod
from functools import wraps
import inspect
def Interface_ABC(cls):
abstract_methods = {}
for name, value in vars(cls).items():
if getattr(value, '__isabstractmethod__', False):
if isinstance(value, classmethod):
abstract_methods[name] = 'classmethod'
elif isinstance(value, staticmethod):
abstract_methods[name] = 'staticmethod'
else:
abstract_methods[name] = 'method'
def decorator(subclass):
for method, method_type in abstract_methods.items():
if not hasattr(subclass, method):
raise NotImplementedError(
f"'{subclass.__name__}' must implement abstract {method_type} '{method}' from interface '{cls.__name__}'"
)
subclass_value = getattr(subclass, method)
if method_type == 'classmethod' and not isinstance(subclass_value, classmethod):
raise TypeError(f"'{method}' must be a classmethod in '{subclass.__name__}'")
elif method_type == 'staticmethod' and not isinstance(subclass_value, staticmethod):
raise TypeError(f"'{method}' must be a staticmethod in '{subclass.__name__}'")
elif method_type == 'method' and (isinstance(subclass_value, (classmethod, staticmethod)) or inspect.isfunction(subclass_value)):
# For normal methods, we accept either functions or methods, as unbound methods are functions in Python 3
pass
else:
raise TypeError(f"'{method}' has incorrect type in '{subclass.__name__}'")
return subclass
return decorator

View File

@@ -1,34 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Helpers
Feature: PostgreSQL Database Helper
"""
# internal
# external
import psycopg2
# from psycopg2 import sql
from pydantic import BaseModel
from flask import Flask
class Helper_DB_PostgreSQL(BaseModel):
app: Flask
def __init__(self, app):
super().__init__(app=app)
# self.app = app
def get_db_connection(self):
return psycopg2.connect(
dbname = self.app.config['DB_NAME'],
user = self.app.config['DB_USER'],
password = self.app.config['DB_PASSWORD'],
host = self.app.config['DB_HOST'],
port = self.app.config['DB_PORT']
)

View File

@@ -12,7 +12,6 @@ Feature: App Helper
# external
from pydantic import BaseModel, ConfigDict
from flask import current_app
# from flask_sqlalchemy import SQLAlchemy
class Helper_App(BaseModel):

View File

@@ -13,7 +13,7 @@ Notes: This architecture does not work with Flask-SQLAlchemy - db connection mus
# external
from pydantic import BaseModel, ConfigDict
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import uuid
@@ -24,7 +24,6 @@ class Helper_DB_MySQL(BaseModel):
def __init__(self, app):
super().__init__(app=app)
# self.app = app
def get_db_connection(self):
db = SQLAlchemy()

View File

@@ -11,17 +11,7 @@ from helpers.helper_app import Helper_App
from typing import Optional
def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# return error message string for output of invalid argument / attribute to user
# ARGUMENTS
# str method - name of parent method which calls this function
# str arg_name - name of argument throwing error
# ? v - erroneous variable
# str v_type - desired / expected variable type
# str arg_type - e.g. argument, attribute
# bool suppress_errors - should outputs not be raised as errors?
# bool suppress_console_outputs
# ARGUMENT VALIDATION
my_f = 'error_msg_str'
# suppress_errors
if not val_bool(suppress_errors, 'suppress_errors', my_f):
@@ -74,21 +64,10 @@ def error_msg_str(v, v_name, method, v_type, suppress_errors = False, suppress_c
return error_msg
else:
raise ValueError(error_msg)
# RETURNS
return f"Invalid {method} {v_type} {v_arg_type} {v_name}. Type = {str(type(v))}. Value = {v}"
def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that myinput is of type bool
# ARGUMENTS
# bool (hopefully) myinput
# str v_name
# str method
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
# validate bool inputs first
v_type = "<class 'bool'>"
my_f = 'val_bool'
if str(type(suppress_errors)) != v_type:
@@ -100,7 +79,6 @@ def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_
return False
raise ValueError(error_msg)
v_type = "<class 'str'>"
# method
valid = True
if str(type(method)) != v_type:
valid = False
@@ -153,23 +131,11 @@ def val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_
print(error_msg)
return False
raise ValueError(error_msg)
# RETURNS
return True
def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type str
# ARGUMENTS
# str (hopefully) v_input
# str v_name
# str method
# optional int min_len
# optional int max_len
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_str'
v_type = "<class 'str'>"
# suppress_errors
@@ -178,7 +144,6 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
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))
return False
# method
valid = True
if str(type(method)) != v_type:
valid = False
@@ -246,10 +211,8 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
return False
raise ValueError(error_msg)
# v_input
# VARIABLE INSTANTIATION
v_type = "<class 'str'>"
valid = True
# METHODS
if str(type(v_input)) != v_type:
valid = False
else:
@@ -267,31 +230,11 @@ def val_str(v_input, v_name, method, min_len = -1, max_len = -1, suppress_errors
print(error_msg)
return False
raise ValueError(error_msg)
# RETURNS
return True
# def val_none(v_input, v_name, method, v_arg_type = 'argument', suppress_errors = False, suppress_console_outputs = False):
# # FUNCTION
# # evaluate if v_input is None
# # ARGUMENTS
# # ARGUMENT VALIDATION
# # VARIABLE INSTANTIATION
# # METHODS
# # RETURNS
def val_int(v_input, v_name, method, v_min: Optional[int] = None, v_max: Optional[int] = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that myinput is of type int, and if not None, limited by v_min and v_max
# ARGUMENTS
# int (hopefully) myinput
# str v_name
# str method
# optional int v_min
# optional int v_max
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_int'
# suppress_errors
val_bool(suppress_errors, 'suppress_errors', my_f)
@@ -315,10 +258,8 @@ def val_int(v_input, v_name, method, v_min: Optional[int] = None, v_max: Optiona
if not val_int(v_max, 'v_max', my_f, None, None, suppress_errors, suppress_console_outputs):
return False
# v_input
# VARIABLE INSTANTIATION
mytype = "<class 'int'>" # str(type(myinput))
mytype = "<class 'int'>"
error_msg = error_msg_str(v_input, v_name, method, mytype, suppress_errors, suppress_console_outputs, v_arg_type)
# METHODS
if not mytype == str(type(v_input)):
if suppress_errors:
if not suppress_console_outputs:
@@ -346,23 +287,11 @@ def val_int(v_input, v_name, method, v_min: Optional[int] = None, v_max: Optiona
print(error_msg + f"\nValue greater than maximum {v_max}.")
return False
raise ValueError(error_msg + f"\nValue greater than maximum {v_max}.")
# RETURNS
return True
def val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type float, and if not None, limited by v_min and v_max
# ARGUMENTS
# float (hopefully) v_input
# str v_name
# str method
# optional float v_min
# optional float v_max
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_float'
# suppress_errors
val_bool(suppress_errors, 'suppress_errors', my_f)
@@ -386,10 +315,8 @@ def val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_erro
if not val_float(v_max, 'v_max', my_f, None, None, suppress_errors, suppress_console_outputs):
return False
# v_input
# VARIABLE INSTANTIATION
mytype = "<class 'float'>" # str(type(myinput))
mytype = "<class 'float'>"
error_msg = error_msg_str(v_input, v_name, method, mytype, suppress_errors, suppress_console_outputs, v_arg_type)
# METHODS
if not mytype == str(type(v_input)):
if suppress_errors:
if not suppress_console_outputs:
@@ -417,20 +344,10 @@ def val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_erro
print(error_msg + f"\nValue greater than maximum {v_max}.")
return False
raise ValueError(error_msg + f"\nValue greater than maximum {v_max}.")
# RETURNS
return True
def input_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# input valid str, int, or bool representation of bool, or else None
# ARGUMENTS
# bool (hopefully) v_input
# str v_name
# str method
# optional str v_arg_type
# optional bool suppress_errors
# optional bool suppress_console_outputs
# ARGUMENT VALIDATION
my_f = 'input_bool'
if v_input is None: return False
# suppress_errors
@@ -446,7 +363,6 @@ def input_bool(v_input, v_name, method, suppress_errors = False, suppress_consol
my_f = method + '.' + my_f
# v_arg_type
if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return None
# METHODS
if not val_bool(v_input, v_name, my_f, True, True):
if not val_int(v_input, v_name, my_f, 0, 1, True, True):
# if str(type(v_input)) == "<class 'bytes'>":
@@ -476,20 +392,10 @@ def input_bool(v_input, v_name, method, suppress_errors = False, suppress_consol
raise ValueError(error_msg)
else:
return False if v_input == 0 else True
# RETURNS
return bool(v_input)
def full_val_bool(v_input, v_name, method, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that bool input is bool or valid equivalent
# ARGUMENTS
# bool (hopefully) my_input
# str v_name
# str method
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'full_val_bool'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -502,23 +408,11 @@ def full_val_bool(v_input, v_name, method, suppress_errors = False, suppress_con
if not val_str(v_name, 'v_name', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False
# v_arg_type
if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False
# RETURNS
return not (str(type(input_bool(v_input, v_name, method, suppress_errors, suppress_console_outputs, v_arg_type))) == "<class 'NoneType'>")
def input_int(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# input int or valid equivalent, or else None
# ARGUMENTS
# int or str v_input
# str v_name
# str method
# v_min
# v_min
# bool suppress_errors
# bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'input_int'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -539,7 +433,6 @@ def input_int(v_input, v_name, method, v_min = None, v_max = None, suppress_erro
if not str(type(v_max)) == "<class 'NoneType'>":
v_max = input_int(v_max, 'v_min', my_f, v_min, None, suppress_errors, suppress_console_outputs)
if str(type(v_max)) == "<class 'NoneType'>": return None
# METHODS
error_msg = error_msg_str(v_input, v_name, method, "<class 'int'>", suppress_errors, suppress_console_outputs, v_arg_type)
# v_input
try:
@@ -562,23 +455,11 @@ def input_int(v_input, v_name, method, v_min = None, v_max = None, suppress_erro
if not suppress_console_outputs:
Helper_App.console_log(f"{error_msg}\nInt input greater than maximum value. Value = {v_input}, maximum = {v_max}.")
return None
# RETURNS
return my_int
def full_val_int(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is int or equivalent, else False, limited by v_min and v_max
# ARGUMENTS
# int (hopefully) v_input
# str v_name
# str method
# optional float v_min
# optional float v_max
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'full_val_int'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -596,23 +477,11 @@ def full_val_int(v_input, v_name, method, v_min = None, v_max = None, suppress_e
if not str(type(v_max)) == "<class 'NoneType'>":
v_max = input_int(v_max, 'v_min', method, v_min, None, suppress_errors, suppress_console_outputs)
if str(type(v_max)) == "<class 'NoneType'>": return False
# RETURNS
return not (str(type(input_int(v_input, v_name, method, v_min, v_max, suppress_errors, suppress_console_outputs))) == "<class 'NoneType'>")
def input_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# input float, else return None
# ARGUMENTS
# float/int/str(numeric) v_input
# str v_name
# str method
# optional float v_min
# optional float v_min
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'input_float'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -633,7 +502,6 @@ def input_float(v_input, v_name, method, v_min = None, v_max = None, suppress_er
if not str(type(v_max)) == "<class 'NoneType'>":
v_max = input_float(v_max, 'v_min', my_f, v_min, None, suppress_errors, suppress_console_outputs)
if str(type(v_max)) == "<class 'NoneType'>": return None
# METHODS
error_msg = error_msg_str(v_input, v_name, method, "<class 'float'>", suppress_errors, suppress_console_outputs, v_arg_type)
# v_input
try:
@@ -656,22 +524,11 @@ def input_float(v_input, v_name, method, v_min = None, v_max = None, suppress_er
if not suppress_console_outputs:
Helper_App.console_log(f"{error_msg}\nInt input greater than maximum value. Value = {v_input}, maximum = {v_max}.")
return None
# RETURNS
return my_float
def full_val_float(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is numeric, and if not False, limited by v_min and v_max
# ARGUMENTS
# float (hopefully) v_input
# str v_name
# str method
# optional float v_min
# optional float v_max
# optional bool suppress_errors
# optional bool suppress_console_outputs
# ARGUMENT VALIDATION
my_f = 'full_val_float'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -692,40 +549,22 @@ def full_val_float(v_input, v_name, method, v_min = None, v_max = None, suppress
if not str(type(v_max)) == "<class 'NoneType'>":
v_max = input_float(v_max, 'v_min', method, v_min, None, suppress_errors, suppress_console_outputs)
if str(type(v_max)) == "<class 'NoneType'>": return False
# RETURNS
return not (str(type(input_float(v_input, v_name, method, v_min, v_max, suppress_errors, suppress_console_outputs))) == "<class 'NoneType'>")
def make_ordinal(n):
# FUNCTION
# Get ordinal representation of number
# ARGUMENTS
# int n
# ARGUMENT VALIDATION
full_val_int(n, 'n', 'make_ordinal', 0)
# VARIABLE INSTANTIATION
n = int(n)
# METHODS
if 11 <= (n % 100):
suffix= 'th'
else:
suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)]
# RETURNS
return str(n) + suffix
def val_type(v_input, v_name, method, v_type, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type v_type
# ARGUMENTS
# v_type (hopefully) v_input
# str v_name
# str method
# str v_type
# optional bool suppress_errors
# optional bool suppress_console_outputs
# str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_type'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -751,22 +590,11 @@ def val_type(v_input, v_name, method, v_type, suppress_errors = False, suppress_
Helper_App.console_log(error_message)
return False
raise ValueError(error_message)
# RETURNS
return True
def val_instance(v_input, v_name, method, v_type, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type v_type
# ARGUMENTS
# v_type (hopefully) v_input
# str v_name
# str method
# type v_type
# optional bool suppress_errors
# optional bool suppress_console_outputs
# str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_type'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -781,41 +609,25 @@ def val_instance(v_input, v_name, method, v_type, suppress_errors = False, suppr
if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False
# v_type
error_message = error_msg_str(v_type, 'v_type', my_f, v_arg_type)
if not isinstance(v_type, type): # mytype == v_type: # f"<class '{v_type}'>":
if suppress_errors:
if not suppress_console_outputs:
Helper_App.console_log(error_message)
return False
raise ValueError(error_message) # val_str(v_type, 'v_type', my_f, 6, -1, suppress_errors, suppress_console_outputs): return False
# v_input
error_message = error_msg_str(v_input, v_name, method, v_arg_type)
# mytype = str(type(v_input))
# if not (v_type == 'int' or v_type == 'bool' or v_type == 'float' or v_type == 'complex' or v_type == 'str' or v_type == 'NoneType'):
if not isinstance(v_input, v_type): # mytype == v_type: # f"<class '{v_type}'>":
if not isinstance(v_type, type):
if suppress_errors:
if not suppress_console_outputs:
Helper_App.console_log(error_message)
return False
raise ValueError(error_message)
# v_input
error_message = error_msg_str(v_input, v_name, method, v_arg_type)
if not isinstance(v_input, v_type):
if suppress_errors:
if not suppress_console_outputs:
Helper_App.console_log(error_message)
return False
raise ValueError(error_message)
# RETURNS
return True
def val_list(v_input, v_name, method, v_type = '', min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs: bool = False, allow_nuns = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type list, and if defined: has v_len elements of type v_type
# ARGUMENTS
# list[v_type] (hopefully) v_input
# str v_name - variable name
# str method - parent method
# str v_type - type of list items
# int min_len - minimum length of list
# int max_len - maximum length of list
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional bool allow_nuns
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_list'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -829,21 +641,14 @@ def val_list(v_input, v_name, method, v_type = '', min_len = -1, max_len = -1, s
# v_arg_type
if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False
# v_type
# if not val_type(v_type, 'v_type', my_f, type, suppress_errors, suppress_console_outputs): return False
if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): return False
# min_len
if not full_val_int(min_len, 'min_len', my_f, None, None if max_len == -1 else max_len, suppress_errors, suppress_console_outputs): return False
# min_len = input_int(min_len, 'min_len', method, None, max_len, suppress_errors, suppress_console_outputs)
# if str(type(min_len)) == "<class 'NoneType'>": return False
# max_len
if not full_val_int(max_len, 'max_len', my_f, None if max_len == -1 else (None if min_len == -1 else min_len), None, suppress_errors, suppress_console_outputs): return False
# if not str(type(max_len)) == "<class 'NoneType'>":
# max_len = input_int(max_len, 'max_len', method, min_len, None, suppress_errors, suppress_console_outputs)
# if str(type(max_len)) == "<class 'NoneType'>": return False
# allow_nuns
if not val_bool(allow_nuns, 'allow_nuns', my_f, suppress_errors, suppress_console_outputs): return False
# v_input
# mytype = str(type(v_input))
error_msg = error_msg_str(v_input, v_name, method, "<class 'list'>")
if not str(type(v_input)) == "<class 'list'>":
if suppress_errors:
@@ -866,7 +671,6 @@ def val_list(v_input, v_name, method, v_type = '', min_len = -1, max_len = -1, s
raise ValueError(error_msg + f'\nInvalid list length. Minimum = {min_len}, length = {L}')
if v_type != '' and L > 0:
for i in range(L):
# mytype = str(type(v_input[i]))
if not (val_type(v_input[i], f'{v_name}[{i}]', my_f, v_type, True) or allow_nuns and val_type(v_input[i], f'{v_name}[{i}]', my_f, "<class 'NoneType'>", True)): # mytype == v_type:
error_msg = error_msg + '\n' + error_msg_str(v_input[i], f'{v_name}[{i}]', my_f, v_type, False, False, 'list element')
if suppress_errors:
@@ -874,25 +678,11 @@ def val_list(v_input, v_name, method, v_type = '', min_len = -1, max_len = -1, s
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# RETURNS
return True
def val_list_instances(v_input, v_name, method, v_type = None, min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs: bool = False, allow_nuns = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type list, and if defined: has v_len elements of type v_type
# ARGUMENTS
# list[v_type] (hopefully) v_input
# str v_name - variable name
# str method - parent method
# type v_type - type of list items
# int min_len - minimum length of list
# int max_len - maximum length of list
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional bool allow_nuns
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_list_instances'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -907,20 +697,12 @@ def val_list_instances(v_input, v_name, method, v_type = None, min_len = -1, max
if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False
# v_type
if not val_type(v_type, 'v_type', my_f, type, suppress_errors, suppress_console_outputs): return False
# if not val_str(v_type, 'v_type', my_f, 6, -1, suppress_errors, suppress_console_outputs): return False
# min_len
if not full_val_int(min_len, 'min_len', my_f, None, None if max_len == -1 else max_len, suppress_errors, suppress_console_outputs): return False
# min_len = input_int(min_len, 'min_len', method, None, max_len, suppress_errors, suppress_console_outputs)
# if str(type(min_len)) == "<class 'NoneType'>": return False
# max_len
if not full_val_int(max_len, 'max_len', my_f, None if max_len == -1 else (None if min_len == -1 else min_len), None, suppress_errors, suppress_console_outputs): return False
# if not str(type(max_len)) == "<class 'NoneType'>":
# max_len = input_int(max_len, 'max_len', method, min_len, None, suppress_errors, suppress_console_outputs)
# if str(type(max_len)) == "<class 'NoneType'>": return False
# allow_nuns
if not val_bool(allow_nuns, 'allow_nuns', my_f, suppress_errors, suppress_console_outputs): return False
# v_input
# mytype = str(type(v_input))
error_msg = error_msg_str(v_input, v_name, method, "<class 'list'>")
if not str(type(v_input)) == "<class 'list'>":
if suppress_errors:
@@ -943,38 +725,19 @@ def val_list_instances(v_input, v_name, method, v_type = None, min_len = -1, max
raise ValueError(error_msg + f'\nInvalid list length. Minimum = {min_len}, length = {L}')
if v_type != '' and L > 0:
for i in range(L):
# mytype = str(type(v_input[i]))
if not (val_instance(v_input[i], f'{v_name}[{i}]', my_f, v_type, True) or allow_nuns and val_instance(v_input[i], f'{v_name}[{i}]', my_f, type(None), True)): # mytype == v_type:
if not (val_instance(v_input[i], f'{v_name}[{i}]', my_f, v_type, True) or allow_nuns and val_instance(v_input[i], f'{v_name}[{i}]', my_f, type(None), True)):
error_msg = error_msg + '\n' + error_msg_str(v_input[i], f'{v_name}[{i}]', my_f, v_type, False, False, 'list element')
if suppress_errors:
if not suppress_console_outputs:
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# RETURNS
return True
def val_nested_list(v_input, v_name, method, depth_i, depth_max, v_type = '', v_min = -1, v_mins = [], v_max = -1, v_maxs = [], suppress_errors = False, suppress_console_outputs = False, allow_nuns = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type list, and if defined: has v_len elements of type v_type
# for nested list of nested-index i
# ARGUMENTS
# list[v_type] (hopefully) v_input
# str v_name
# str method
# int depth_i - current depth of nesting of lists
# int depth_max - maximum depth of nesting of lists - base 0
# Optional[str] v_type - type of list items
# Optional[int] v_min - minimum sublist size
# Optional[list[int]] v_mins - minimum list sizes
# Optional[int] v_max - maximum sublist size
# Optional[list[int]] v_maxs - maximum list sizes
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional bool allow_nuns
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_nested_list'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -1017,7 +780,6 @@ def val_nested_list(v_input, v_name, method, depth_i, depth_max, v_type = '', v_
if not suppress_console_outputs:
Helper_App.console_log(error_msg)
return False
# METHODS
L = len(v_input)
if L == 0:
if v_min > -1:
@@ -1048,30 +810,12 @@ def val_nested_list(v_input, v_name, method, depth_i, depth_max, v_type = '', v_
if not suppress_console_outputs:
Helper_App.console_log(error_msg)
return False
# RETURNS
return True
def val_nested_list_instances(v_input, v_name, method, depth_i, depth_max, v_type = '', v_min = -1, v_mins = [], v_max = -1, v_maxs = [], suppress_errors = False, suppress_console_outputs = False, allow_nuns = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type list, and if defined: has v_len elements of type v_type
# for nested list of nested-index i
# ARGUMENTS
# list[v_type] (hopefully) v_input
# str v_name
# str method
# int depth_i - current depth of nesting of lists
# int depth_max - maximum depth of nesting of lists - base 0
# Optional[str] v_type - type of list items
# Optional[int] v_min - minimum sublist size
# Optional[list[int]] v_mins - minimum list sizes
# Optional[int] v_max - maximum sublist size
# Optional[list[int]] v_maxs - maximum list sizes
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional bool allow_nuns
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_nested_list'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -1085,7 +829,6 @@ def val_nested_list_instances(v_input, v_name, method, depth_i, depth_max, v_typ
# v_arg_type
if not val_str(v_arg_type, 'v_arg_type', my_f, 1, -1, suppress_errors, suppress_console_outputs): return False
# v_type
# if not val_str(v_type, 'v_type', my_f, -1, -1, suppress_errors, suppress_console_outputs): return False
if not val_type(v_type, 'v_type', my_f, type, suppress_errors, suppress_console_outputs): return False
# v_min
if not val_int(v_min, 'v_min', my_f, -1, None, suppress_errors, suppress_console_outputs): return False
@@ -1108,13 +851,12 @@ def val_nested_list_instances(v_input, v_name, method, depth_i, depth_max, v_typ
# allow_nuns
if not val_bool(allow_nuns, 'allow_nuns', my_f, suppress_errors, suppress_console_outputs): return False
# v_input
mytype = v_type if depth_i == depth_max else list # "<class 'list'>"
mytype = v_type if depth_i == depth_max else list
error_msg = error_msg_str(v_input, v_name, method, mytype, suppress_errors, suppress_console_outputs, v_arg_type)
if not val_list_instances(v_input, v_name, method, mytype, v_min, v_max, suppress_errors, suppress_console_outputs, allow_nuns, v_arg_type):
if not suppress_console_outputs:
Helper_App.console_log(error_msg)
return False
# METHODS
L = len(v_input)
if L == 0:
if v_min > -1:
@@ -1145,23 +887,11 @@ def val_nested_list_instances(v_input, v_name, method, depth_i, depth_max, v_typ
if not suppress_console_outputs:
Helper_App.console_log(error_msg)
return False
# RETURNS
return True
def val_url(v_input, v_name, method, min_len = 12, max_len = -1, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# FUNCTION
# validate that v_input is of type str
# ARGUMENTS
# str (hopefully) v_input
# str v_name
# str method
# optional int min_len
# optional int max_len
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
_m = 'val_url'
v_type = "<class 'str'>"
val_bool(suppress_errors, 'suppress_errors', _m)
@@ -1181,7 +911,6 @@ def val_url(v_input, v_name, method, min_len = 12, max_len = -1, suppress_errors
if not val_int(max_len, 'max_len', _m, -1, None, suppress_errors, suppress_console_outputs): return False
# v_input
if not val_str(v_input, v_name, method, min_len, -1, suppress_errors, suppress_console_outputs): return False
# METHODS
error_msg = error_msg_str(v_input, 'v_input', _m, "<class 'str'>")
if not (v_input[:8] == r'https://' or v_input[:7] == r'http://'):
if suppress_errors:
@@ -1189,40 +918,11 @@ def val_url(v_input, v_name, method, min_len = 12, max_len = -1, suppress_errors
Helper_App.console_log(error_msg)
return False
raise ValueError(error_msg)
# RETURNS
return True
# def val_nparray(v_input, v_name, method, v_min = None, v_max = None, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument'):
# # FUNCTION
# # validate v_input is numpy ndarray
# # ARGUMENTS
# # numpy.ndarray v_input
# # str v_name
# # str method
# #
# # ARGUMENT VALIDATION
# # METHODS
# # RETURNS
def val_DataFrame(v_input, v_name, method, v_types=[], min_col=-1, max_col=-1, cols=[], min_sz=-1, max_sz=-1, suppress_errors=False, suppress_console_outputs=False, v_arg_type='argument'):
# FUNCTION
# validate that v_input is of type list, and if defined: has v_len elements of type v_type
# for nested list of nested-index i
# ARGUMENTS
# pandas.DataFrame (hopefully) v_input
# str v_name
# str method
# optional list[str] v_type - column datatypes
# optional int min_col - minimum number of columns
# optional int max_col - maximum number of columns
# optional list[str] cols - column names
# optional int min_sz - minimum length of columns
# optional int max_sz - maximum length of columns
# optional bool suppress_errors
# optional bool suppress_console_outputs
# optional str v_arg_type
# ARGUMENT VALIDATION
my_f = 'val_DataFrame'
val_bool(suppress_errors, 'suppress_errors', my_f)
if not val_bool(suppress_console_outputs, 'suppress_console_outputs', my_f, suppress_errors):
@@ -1259,7 +959,6 @@ def val_DataFrame(v_input, v_name, method, v_types=[], min_col=-1, max_col=-1, c
raise ValueError(error_msg)
# v_input
if not val_type(v_input, v_name, my_f, "<class 'pandas.core.frame.DataFrame'>", suppress_errors, suppress_console_outputs, v_arg_type): return False
# METHODS
error_msg = error_msg_str(v_input, v_name, my_f, "<class 'pandas.core.frame.DataFrame'>", v_arg_type=v_arg_type)
n_c = len(v_input.columns)
if (min_col > 0 and n_c < min_col) or (max_col > 0 and n_c > max_col):
@@ -1291,7 +990,6 @@ def val_DataFrame(v_input, v_name, method, v_types=[], min_col=-1, max_col=-1, c
Helper_App.console_log(error_msg + f'\nInvalid column heading for column {v_input.columns[col_i]}')
return False
raise ValueError(error_msg + f'\nInvalid column heading for column {v_input.columns[col_i]}')
# RETURNS
return True

View File

@@ -1,35 +1,5 @@
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 27 12:33:59 2023
@author: Edward Middleton-Smith
Argument Validation
"""
# CLASSES
# ATTRIBUTE DECLARATION
# METHODS
# FUNCTION
# ARGUMENTS
# ARGUMENT VALIDATION
# ATTRIBUTE + VARIABLE INSTANTIATION
# METHODS
# RETURNS
# NORMAL METHODS
# FUNCTION
# ARGUMENTS
# ARGUMENT VALIDATION
# VARIABLE INSTANTIATION
# METHODS
# RETURNS
# IMPORTS
# CLASSES
# METHODS
def get_enum_member_by_text(enum_class, text):
for member in enum_class.__members__.values():
if member.name == text:

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

@@ -1,3 +1,5 @@
User-agent: *
Disallow: /qa
Disallow: /dev
Disallow: /dev
Disallow: /contact
Disallow: /*.partsltd.co.uk/

View File

@@ -1,54 +0,0 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Backend
Feature: Controller - Webpage routing
Description:
Defines the routes and view functions for each page.
Manages the interaction between the frontend and backend.
"""
from flask import render_template, url_for, Blueprint
from app import app
from app.forms import Form_Contact
# from forms import MyForm
# from app import MyForm
from model_view_contact import Model_View_Contact
"""
@app.route('/', methods=['GET'])
def home():
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', methods=['GET', 'POST'])
def contact():
form = Form_Contact()
if form.validate_on_submit():
# Handle form submission
email = form.sender_email.data
CC = form.sender_CC.data
name = form.sender_name.data
msg = form.sender_message.data
# return render_template('contact.html', form=form)
# return render_template('_contact.html', title='Contact Us')
return render_template('contact.html', model=Model_View_Contact(form))
@app.route('/about')
def about():
return render_template('about.html')
@app.route('/contact', methods=['GET', 'POST'])
def contact():
form = MyForm()
if form.validate_on_submit():
# Handle form submission
pass
return render_template('contact.html', form=form)
"""

6
run.py
View File

@@ -11,7 +11,11 @@ Runs project.
"""
from app import app
import os
from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv())
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=(os.getenv('FLASK_ENV') == 'development'))
# app.run(debug=True, host="0.0.0.0", port=5000)

File diff suppressed because it is too large Load Diff

View File

@@ -1,293 +0,0 @@
/* Clear Store DataBase */
-- Drop dependencies
DROP TABLE IF EXISTS Shop_Calc_User_Temp;
DROP TABLE IF EXISTS tmp_Msg_Error;
DROP TABLE IF EXISTS tmp_Currency;
DROP TABLE IF EXISTS tmp_Delivery_Region;
DROP TABLE IF EXISTS tmp_Region;
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_Shop_Product_p_shop_calc_user;
DROP TABLE IF EXISTS tmp_Shop_Image;
DROP TABLE IF EXISTS tmp_Shop_Variation;
DROP TABLE IF EXISTS tmp_Shop_Discount;
DROP TABLE IF EXISTS tmp_Discount;
DROP TABLE IF EXISTS tmp_Shop_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_Shop_Supplier_Purchase_Order;
DROP TABLE IF EXISTS tmp_Shop_Supplier;
DROP TABLE IF EXISTS tmp_Shop_Manufacturing_Purchase_Order_Product_Link;
DROP TABLE IF EXISTS tmp_Shop_Manufacturing_Purchase_Order;
DROP TABLE IF EXISTS tmp_Shop_Customer;
-- Delete old tables
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 Shop_Customer_Sales_Order_Audit;
DROP TABLE IF EXISTS Shop_Customer_Sales_Order;
DROP TABLE IF EXISTS Shop_Customer_Audit;
DROP TABLE IF EXISTS Shop_Customer;
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 Shop_Manufacturing_Purchase_Order_Audit;
DROP TABLE IF EXISTS Shop_Manufacturing_Purchase_Order;
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 Shop_Supplier_Purchase_Order_Audit;
DROP TABLE IF EXISTS Shop_Supplier_Purchase_Order;
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_Supplier_Audit;
DROP TABLE IF EXISTS Shop_Supplier;
DROP TABLE IF EXISTS Shop_User_Order_Product_Link_Audit;
DROP TABLE IF EXISTS Shop_User_Order_Product_Link;
DROP TABLE IF EXISTS Shop_User_Order_Audit;
DROP TABLE IF EXISTS Shop_User_Order;
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_Address_Audit;
DROP TABLE IF EXISTS Shop_Address;
DROP TABLE IF EXISTS Shop_User_Role_Link_Audit;
DROP TABLE IF EXISTS Shop_User_Role_Link;
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_Delivery_Option_Audit;
DROP TABLE IF EXISTS Shop_Delivery_Option;
DROP TABLE IF EXISTS Shop_Image_Audit;
DROP TABLE IF EXISTS Shop_Image;
DROP TABLE IF EXISTS Shop_Image_Type_Audit;
DROP TABLE IF EXISTS Shop_Image_Type;
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_Audit;
DROP TABLE IF EXISTS Shop_Product_Permutation_Variation_Link;
DROP TABLE IF EXISTS Shop_Product_Permutation_Audit;
DROP TABLE IF EXISTS Shop_Product_Permutation;
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_Variation_Type_Audit;
DROP TABLE IF EXISTS Shop_Variation_Type;
DROP TABLE IF EXISTS Shop_Product_Audit;
DROP TABLE IF EXISTS Shop_Product;
DROP TABLE IF EXISTS Shop_Tax_Or_Surcharge_Audit;
DROP TABLE IF EXISTS Shop_Tax_Or_Surcharge;
DROP TABLE IF EXISTS Shop_Currency_Audit;
DROP TABLE IF EXISTS Shop_Currency;
DROP TABLE IF EXISTS Shop_Delivery_Region_Branch_Audit;
DROP TABLE IF EXISTS Shop_Delivery_Region_Branch;
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_Audit;
DROP TABLE IF EXISTS Shop_Region;
DROP TABLE IF EXISTS Shop_Interval_Recurrence_Audit;
DROP TABLE IF EXISTS Shop_Interval_Recurrence;
DROP TABLE IF EXISTS Shop_Product_Category_Audit;
DROP TABLE IF EXISTS Shop_Product_Category;
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_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_Msg_Error_Type;
DROP TABLE IF EXISTS Shop_Product_Change_Set;
DO $$
BEGIN
RAISE NOTICE 'TABLE DELETION COMPLETE';
END $$;
DROP FUNCTION IF EXISTS fn_shop_user_eval;
DROP FUNCTION IF EXISTS p_shop_calc_user;
DROP PROCEDURE IF EXISTS fn_shop_user_eval;
DROP PROCEDURE IF EXISTS p_shop_calc_user;
DROP FUNCTION IF EXISTS fn_shop_save_product;
DROP FUNCTION IF EXISTS p_shop_save_product;
DROP PROCEDURE IF EXISTS fn_shop_save_product;
DROP PROCEDURE IF EXISTS p_shop_save_product;
DROP FUNCTION IF EXISTS fn_shop_save_supplier;
DROP FUNCTION IF EXISTS p_shop_save_supplier;
DROP PROCEDURE IF EXISTS fn_shop_save_supplier;
DROP PROCEDURE IF EXISTS p_shop_save_supplier;
DROP FUNCTION IF EXISTS fn_shop_save_supplier_purchase_order;
DROP FUNCTION IF EXISTS p_shop_save_supplier_purchase_order;
DROP PROCEDURE IF EXISTS fn_shop_save_supplier_purchase_order;
DROP PROCEDURE IF EXISTS p_shop_save_supplier_purchase_order;
DROP FUNCTION IF EXISTS fn_shop_save_manufacturing_purchase_order;
DROP FUNCTION IF EXISTS p_shop_save_manufacturing_purchase_order;
DROP PROCEDURE IF EXISTS fn_shop_save_manufacturing_purchase_order;
DROP PROCEDURE IF EXISTS p_shop_save_manufacturing_purchase_order;
DROP FUNCTION IF EXISTS fn_shop_save_customer;
DROP FUNCTION IF EXISTS p_shop_save_customer;
DROP PROCEDURE IF EXISTS fn_shop_save_customer;
DROP PROCEDURE IF EXISTS p_shop_save_customer;
DROP FUNCTION IF EXISTS fn_shop_save_customer_sales_order;
DROP FUNCTION IF EXISTS p_shop_save_customer_sales_order;
DROP PROCEDURE IF EXISTS fn_shop_save_customer_sales_order;
DROP PROCEDURE IF EXISTS p_shop_save_customer_sales_order;
DROP FUNCTION IF EXISTS fn_shop_save_user;
DROP FUNCTION IF EXISTS p_shop_save_user;
DROP PROCEDURE IF EXISTS fn_shop_save_user;
DROP PROCEDURE IF EXISTS p_shop_save_user;
DROP FUNCTION IF EXISTS fn_shop_save_user_basket;
DROP FUNCTION IF EXISTS p_shop_save_user_basket;
DROP PROCEDURE IF EXISTS fn_shop_save_user_basket;
DROP PROCEDURE IF EXISTS p_shop_save_user_basket;
DROP FUNCTION IF EXISTS fn_shop_get_many_product;
DROP FUNCTION IF EXISTS p_shop_get_many_product;
DROP PROCEDURE IF EXISTS fn_shop_get_many_product;
DROP PROCEDURE IF EXISTS p_shop_get_many_product;
DROP FUNCTION IF EXISTS fn_shop_get_many_role_permission;
DROP FUNCTION IF EXISTS p_shop_get_many_role_permission;
DROP PROCEDURE IF EXISTS fn_shop_get_many_role_permission;
DROP PROCEDURE IF EXISTS p_shop_get_many_role_permission;
DROP FUNCTION IF EXISTS fn_shop_get_many_currency;
DROP FUNCTION IF EXISTS p_shop_get_many_currency;
DROP PROCEDURE IF EXISTS fn_shop_get_many_currency;
DROP PROCEDURE IF EXISTS p_shop_get_many_currency;
DROP FUNCTION IF EXISTS fn_shop_get_many_region;
DROP FUNCTION IF EXISTS p_shop_get_many_region;
DROP PROCEDURE IF EXISTS fn_shop_get_many_region;
DROP PROCEDURE IF EXISTS p_shop_get_many_region;
DROP FUNCTION IF EXISTS fn_shop_get_many_user_order;
DROP FUNCTION IF EXISTS p_shop_get_many_user_order;
DROP PROCEDURE IF EXISTS fn_shop_get_many_user_order;
DROP PROCEDURE IF EXISTS p_shop_get_many_user_order;
DROP FUNCTION IF EXISTS fn_shop_get_many_stripe_product_new;
DROP FUNCTION IF EXISTS p_shop_get_many_stripe_product_new;
DROP PROCEDURE IF EXISTS fn_shop_get_many_stripe_product_new;
DROP PROCEDURE IF EXISTS p_shop_get_many_stripe_product_new;
DROP FUNCTION IF EXISTS fn_shop_get_many_stripe_price_new;
DROP FUNCTION IF EXISTS p_shop_get_many_stripe_price_new;
DROP PROCEDURE IF EXISTS fn_shop_get_many_stripe_price_new;
DROP PROCEDURE IF EXISTS p_shop_get_many_stripe_price_new;
DROP FUNCTION IF EXISTS fn_shop_get_many_supplier;
DROP FUNCTION IF EXISTS p_shop_get_many_supplier;
DROP PROCEDURE IF EXISTS fn_shop_get_many_supplier;
DROP PROCEDURE IF EXISTS p_shop_get_many_supplier;
DROP FUNCTION IF EXISTS fn_shop_get_many_supplier_purchase_order;
DROP FUNCTION IF EXISTS p_shop_get_many_supplier_purchase_order;
DROP PROCEDURE IF EXISTS fn_shop_get_many_supplier_purchase_order;
DROP PROCEDURE IF EXISTS p_shop_get_many_supplier_purchase_order;
DROP FUNCTION IF EXISTS fn_shop_get_many_manufacturing_purchase_order;
DROP FUNCTION IF EXISTS p_shop_get_many_manufacturing_purchase_order;
DROP PROCEDURE IF EXISTS fn_shop_get_many_manufacturing_purchase_order;
DROP PROCEDURE IF EXISTS p_shop_get_many_manufacturing_purchase_order;
DROP FUNCTION IF EXISTS fn_shop_get_many_customer;
DROP FUNCTION IF EXISTS p_shop_get_many_customer;
DROP PROCEDURE IF EXISTS fn_shop_get_many_customer;
DROP PROCEDURE IF EXISTS p_shop_get_many_customer;
DROP FUNCTION IF EXISTS fn_shop_get_many_customer_sales_order;
DROP FUNCTION IF EXISTS p_shop_get_many_customer_sales_order;
DROP PROCEDURE IF EXISTS fn_shop_get_many_customer_sales_order;
DROP PROCEDURE IF EXISTS p_shop_get_many_customer_sales_order;

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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
comment VARCHAR(4000),
updated_last_on TIMESTAMP,
updated_last_by VARCHAR(100)
);

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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
comment VARCHAR(4000),
updated_last_on TIMESTAMP,
updated_last_by VARCHAR(100)
);

View File

@@ -1,21 +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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50),
name VARCHAR(255),
priority INTEGER NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Access_Level_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_User_Change_Set(id_change_set)
);

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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
comment VARCHAR(4000),
updated_last_on TIMESTAMP,
updated_last_by VARCHAR(100)
);

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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_access_level INTEGER 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(255),
value_new VARCHAR(255),
id_change_set INTEGER 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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50) NOT NULL,
name VARCHAR(200) 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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50),
name VARCHAR(100),
extension VARCHAR(50),
created_on TIMESTAMP,
created_by INT,
updated_last_on TIMESTAMP,
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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_type INTEGER 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(100),
value_new VARCHAR(100),
created_on TIMESTAMP,
created_by INT,
updated_last_on TIMESTAMP,
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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
quantity_max REAL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_general INTEGER 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(100),
value_new VARCHAR(100),
id_change_set INTEGER 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,21 +0,0 @@
-- Categories
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Category';
CREATE TABLE IF NOT EXISTS Shop_Product_Category (
id_category INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50),
name VARCHAR(255),
description VARCHAR(4000),
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Product_Category_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Category Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Category_Audit';
CREATE TABLE IF NOT EXISTS Shop_Product_Category_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_category INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Category_Audit_id_category
FOREIGN KEY (id_category)
REFERENCES Shop_Product_Category(id_category)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(4000),
value_new VARCHAR(4000),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Category_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,20 +0,0 @@
-- Recurrence Interval
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Interval_Recurrence';
CREATE TABLE IF NOT EXISTS Shop_Interval_Recurrence (
id_interval INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50),
name VARCHAR(255),
name_plural VARCHAR(256),
active BOOLEAN NOT NULL DEFAULT TRUE,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Interval_Recurrence_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Recurrence Interval Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Interval_Recurrence_Audit';
CREATE TABLE IF NOT EXISTS Shop_Interval_Recurrence_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_interval INTEGER NOT NULL,
CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_interval
FOREIGN KEY (id_interval)
REFERENCES Shop_Interval_Recurrence(id_interval)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(256),
value_new VARCHAR(256),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,20 +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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50) NOT NULL,
name VARCHAR(200) NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_region INTEGER 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(200),
value_new VARCHAR(200),
id_change_set INTEGER 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,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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_region_parent INTEGER 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 INTEGER NOT NULL,
CONSTRAINT FK_Shop_Region_Branch_id_region_child
FOREIGN KEY (id_region_child)
REFERENCES Shop_Region(id_region)
ON UPDATE RESTRICT,
-- depth INTEGER NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Region_Branch_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_Branch_Audit';
CREATE TABLE IF NOT EXISTS Shop_Region_Branch_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_branch INTEGER 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(10),
value_new VARCHAR(10),
id_change_set INTEGER 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,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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50) NOT NULL,
name VARCHAR(255) NOT NULL,
symbol VARCHAR(1) NOT NULL,
factor_from_GBP REAL NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
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

@@ -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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_currency INTEGER 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(255),
value_new VARCHAR(255),
id_change_set INTEGER 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,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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50) NOT NULL,
name VARCHAR(200) NOT NULL,
id_region_buyer INTEGER NOT NULL,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_id_region_buyer
FOREIGN KEY (id_region_buyer)
REFERENCES Shop_Region(id_region),
id_region_seller INTEGER NOT NULL,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_id_region_seller
FOREIGN KEY (id_region_seller)
REFERENCES Shop_Region(id_region),
id_currency INTEGER,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_id_currency
FOREIGN KEY (id_currency)
REFERENCES Shop_Currency(id_currency)
ON UPDATE RESTRICT,
fixed_fee REAL NOT NULL DEFAULT 0,
multiplier REAL NOT NULL DEFAULT 1 CHECK (multiplier > 0),
apply_fixed_fee_before_multiplier BOOLEAN NOT NULL DEFAULT TRUE,
quantity_min REAL NOT NULL DEFAULT 0,
quantity_max REAL NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Tax_Or_Surcharge_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_tax INTEGER 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(200),
value_new VARCHAR(200),
id_change_set INTEGER 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

@@ -1,48 +0,0 @@
-- Products
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product';
CREATE TABLE IF NOT EXISTS Shop_Product (
id_product INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name VARCHAR(255) NOT NULL,
-- description VARCHAR(4000),
id_category INTEGER NOT NULL,
has_variations BOOLEAN NOT NULL,
/*
price_GBP_full REAL,
price_GBP_min REAL,
-- ratio_discount_overall REAL NOT NULL DEFAULT 0,
CONSTRAINT FK_Shop_Product_id_category
FOREIGN KEY (id_category)
REFERENCES Shop_Product_Category(id_category)
ON UPDATE RESTRICT,
latency_manuf INTEGER,
quantity_min REAL,
quantity_max REAL,
quantity_step REAL,
quantity_stock REAL,
is_subscription BOOLEAN,
id_unit_measurement_interval_recurrence INTEGER,
CONSTRAINT FK_Shop_Product_id_unit_measurement_interval_recurrence
FOREIGN KEY (id_unit_measurement_interval_recurrence)
REFERENCES Shop_Interval_Recurrence(id_interval),
count_interval_recurrence INTEGER,
*/
id_access_level_required INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_id_access_level_required
FOREIGN KEY (id_access_level_required)
REFERENCES Shop_Access_Level(id_access_level),
-- id_stripe_product VARCHAR(100),
-- id_stripe_price VARCHAR(100) NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Product_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Products
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Audit';
CREATE TABLE IF NOT EXISTS Shop_Product_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_product INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Audit_id_product
FOREIGN KEY (id_product)
REFERENCES Shop_Product(id_product)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(255),
value_new VARCHAR(255),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,21 +0,0 @@
-- Variation Types
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Variation_Type';
CREATE TABLE IF NOT EXISTS Shop_Variation_Type (
id_type INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50),
name VARCHAR(255),
name_plural VARCHAR(256),
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Variation_Type_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Variation Type Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Variation_Type_Audit';
CREATE TABLE IF NOT EXISTS Shop_Variation_Type_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_type INTEGER NOT NULL,
CONSTRAINT FK_Shop_Variation_Type_Audit_id_type
FOREIGN KEY (id_type)
REFERENCES Shop_Variation_Type(id_type)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(256),
value_new VARCHAR(256),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Variation_Type_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,25 +0,0 @@
-- Variations
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Variation';
CREATE TABLE Shop_Variation (
id_variation INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_type INTEGER NOT NULL,
CONSTRAINT FK_Shop_Variation_id_type
FOREIGN KEY (id_type)
REFERENCES Shop_Variation_Type(id_type)
ON UPDATE RESTRICT,
code VARCHAR(50),
name VARCHAR(255),
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Variation_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Variation Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Variation_Audit';
CREATE TABLE IF NOT EXISTS Shop_Variation_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_variation INTEGER NOT NULL,
CONSTRAINT FK_Shop_Variation_Audit_id_variation
FOREIGN KEY (id_variation)
REFERENCES Shop_Variation(id_variation)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(255),
value_new VARCHAR(255),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Variation_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,47 +0,0 @@
-- Product Permutation
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Permutation';
CREATE TABLE IF NOT EXISTS Shop_Product_Permutation (
id_permutation INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_product INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Variation_Link_id_product
FOREIGN KEY (id_product)
REFERENCES Shop_Product(id_product)
ON UPDATE RESTRICT,
-- name VARCHAR(255) NOT NULL,
description VARCHAR(4000) NOT NULL,
cost_local REAL NOT NULL,
id_currency_cost INTEGER NOT NULL,
profit_local_min REAL NOT NULL,
-- id_currency_profit_min INTEGER NOT NULL,
latency_manufacture INTEGER NOT NULL,
quantity_min REAL NOT NULL,
quantity_max REAL NOT NULL,
quantity_step REAL NOT NULL,
quantity_stock REAL NOT NULL,
is_subscription BOOLEAN NOT NULL,
id_unit_measurement_interval_recurrence INTEGER,
CONSTRAINT FK_Shop_Product_Permutation_id_unit_measurement_interval_recurrence
FOREIGN KEY (id_unit_measurement_interval_recurrence)
REFERENCES Shop_Interval_Recurrence(id_interval),
count_interval_recurrence INTEGER,
/*
id_access_level_required INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Permutation_id_access_level_required
FOREIGN KEY (id_access_level_required)
REFERENCES Shop_Access_Level(id_access_level),
*/
id_stripe_product VARCHAR(100) NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Product_Variation_Link_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,23 +0,0 @@
-- Product Permutation Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Permutation_Audit';
CREATE TABLE IF NOT EXISTS Shop_Product_Permutation_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_permutation INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Permutation_Audit_id_permutation
FOREIGN KEY (id_permutation)
REFERENCES Shop_Product_Permutation(id_permutation)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(4000),
value_new VARCHAR(4000),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Permutation_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
ON UPDATE RESTRICT
);

View File

@@ -1,28 +0,0 @@
-- Product Permutation Variation Link
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Permutation_Variation_Link';
CREATE TABLE IF NOT EXISTS Shop_Product_Permutation_Variation_Link (
id_link INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_permutation INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Permutation_Variation_Link_id_permutation
FOREIGN KEY (id_permutation)
REFERENCES Shop_Product_Permutation(id_permutation)
ON UPDATE RESTRICT,
id_variation INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Permutation_Variation_Link_id_variation
FOREIGN KEY (id_variation)
REFERENCES Shop_Variation(id_variation)
ON UPDATE RESTRICT,
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Product_Permutation_Variation_Link_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,23 +0,0 @@
-- Product Permutation Variation Link Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Permutation_Variation_Link_Audit';
CREATE TABLE IF NOT EXISTS Shop_Product_Permutation_Variation_Link_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_link INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Permutation_Variation_Link_Audit_id_link
FOREIGN KEY (id_link)
REFERENCES Shop_Product_Permutation_Variation_Link(id_link)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(10),
value_new VARCHAR(10),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Permutation_Variation_Link_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
ON UPDATE RESTRICT
);

View File

@@ -1,40 +0,0 @@
-- Product Currency Region link
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Currency_Region_Link';
CREATE TABLE IF NOT EXISTS Shop_Product_Currency_Region_Link (
id_link INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_product INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_product
FOREIGN KEY (id_product)
REFERENCES Shop_Product(id_product)
ON UPDATE RESTRICT,
id_permutation INTEGER NULL,
CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_permutation
FOREIGN KEY (id_permutation)
REFERENCES Shop_Product_Permutation(id_permutation)
ON UPDATE RESTRICT,
id_currency INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_currency
FOREIGN KEY (id_currency)
REFERENCES Shop_Currency(id_currency)
ON UPDATE RESTRICT,
id_region_purchase INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_region_purchase
FOREIGN KEY (id_region_purchase)
REFERENCES Shop_Region(id_region)
ON UPDATE RESTRICT,
price_local_VAT_incl REAL NULL,
price_local_VAT_excl REAL NULL,
id_stripe_price VARCHAR(200),
active BOOLEAN NOT NULL DEFAULT TRUE,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,22 +0,0 @@
-- Product Currency Region Link Audits
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Currency_Region_Link_Audit';
CREATE TABLE IF NOT EXISTS Shop_Product_Currency_Region_Link_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_link INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Currency_Region_Link_Audit_id_link
FOREIGN KEY (id_link)
REFERENCES Shop_Product_Currency_Region_Link(id_link)
ON UPDATE RESTRICT,
name_field VARCHAR(50),
value_prev VARCHAR(10),
value_new VARCHAR(10),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Product_Currency_Region_Link_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,21 +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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
code VARCHAR(50),
name VARCHAR(255),
name_plural VARCHAR(256),
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
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 INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_type INTEGER 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(256),
value_new VARCHAR(256),
id_change_set INTEGER 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

@@ -1,35 +0,0 @@
-- Images
SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Image';
CREATE TABLE IF NOT EXISTS Shop_Image (
id_image INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_type_image INTEGER NOT NULL,
CONSTRAINT FK_Shop_Image_id_type_image
FOREIGN KEY (id_type_image)
REFERENCES Shop_Image_Type(id_type),
id_type_file INTEGER NOT NULL,
CONSTRAINT FK_Shop_Image_id_type_file
FOREIGN KEY (id_type_file)
REFERENCES File_Type(id_type),
id_product INTEGER NULL,
CONSTRAINT FK_Shop_Image_id_product
FOREIGN KEY (id_product)
REFERENCES Shop_Product(id_product),
id_permutation INTEGER NULL,
CONSTRAINT FK_Shop_Image_id_permutation
FOREIGN KEY (id_permutation)
REFERENCES Shop_Product_Permutation(id_permutation),
url VARCHAR(255),
active BOOLEAN NOT NULL DEFAULT TRUE,
display_order INTEGER NOT NULL,
created_on TIMESTAMP,
created_by INT,
id_change_set INTEGER,
CONSTRAINT FK_Shop_Image_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

View File

@@ -1,21 +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_Audit';
CREATE TABLE IF NOT EXISTS Shop_Image_Audit (
id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
id_image INTEGER NOT NULL,
CONSTRAINT FK_Shop_Image_Audit_id_image
FOREIGN KEY (id_image)
REFERENCES Shop_Image(id_image),
name_field VARCHAR(50),
value_prev VARCHAR(10),
value_new VARCHAR(10),
id_change_set INTEGER NOT NULL,
CONSTRAINT FK_Shop_Image_Audit_id_change_set
FOREIGN KEY (id_change_set)
REFERENCES Shop_Product_Change_Set(id_change_set)
);

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