Initial commit
This commit is contained in:
11
business_objects/__init__.py
Normal file
11
business_objects/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Module Initialisation
|
||||
Feature: Business Objects
|
||||
|
||||
Description:
|
||||
Initialises business objects module.
|
||||
"""
|
||||
BIN
business_objects/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/basket.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/basket.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/category.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/category.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/currency.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/currency.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/delivery_option.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/delivery_option.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/delivery_region.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/delivery_region.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/discount.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/discount.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/image.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/image.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/order.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/order.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/product.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/product.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/sql_error.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/sql_error.cpython-311.pyc
Normal file
Binary file not shown.
BIN
business_objects/__pycache__/variation.cpython-311.pyc
Normal file
BIN
business_objects/__pycache__/variation.cpython-311.pyc
Normal file
Binary file not shown.
164
business_objects/basket.py
Normal file
164
business_objects/basket.py
Normal file
@@ -0,0 +1,164 @@
|
||||
"""
|
||||
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.product import Product, Product_Filters
|
||||
from business_objects.discount import Discount
|
||||
from business_objects.delivery_option import Delivery_Option
|
||||
# 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
|
||||
# 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 make_from_product_and_quantity_and_VAT_included(product, quantity, is_included_VAT):
|
||||
# Initialiser - validation
|
||||
_m = 'Basket_Item.make_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_discount(self, discount):
|
||||
av.val_instance(discount, 'discount', 'Basket_Item.add_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():
|
||||
items: list
|
||||
def __init__(self):
|
||||
self.items = []
|
||||
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)
|
||||
print(f'ids_permutation_basket = {ids_permutation}')
|
||||
print(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 {'items': self.to_json_list()}
|
||||
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:
|
||||
print(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
|
||||
273
business_objects/category.py
Normal file
273
business_objects/category.py
Normal file
@@ -0,0 +1,273 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Category Business Object
|
||||
|
||||
Description:
|
||||
Business object for product
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
from business_objects.product import Product, Product_Permutation, Price
|
||||
from business_objects.variation import Variation
|
||||
from business_objects.image import Image
|
||||
from business_objects.delivery_option import Delivery_Option
|
||||
from business_objects.discount import Discount
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
# CLASSES
|
||||
class Enum_Product_Category(Enum):
|
||||
ASSISTIVE_DEVICES = 0
|
||||
HOME_DECOR = 1
|
||||
MISCELLANEOUS = 99
|
||||
|
||||
def text(self):
|
||||
return Enum_Product_Category.Enum_Product_Category_Text(self)
|
||||
|
||||
def Enum_Product_Category_Text(category):
|
||||
av.val_instance(category, 'category', 'Product_Category_Enum_Text', Enum_Product_Category)
|
||||
if category == Enum_Product_Category.ASSISTIVE_DEVICES:
|
||||
return 'Assistive devices'
|
||||
elif category == Enum_Product_Category.HOME_DECOR:
|
||||
return 'Home decor'
|
||||
else:
|
||||
return 'Other'
|
||||
|
||||
def get_member_by_text(text):
|
||||
av.val_str(text, 'text', 'Enum_Product_Category.get_member_by_text')
|
||||
return data_types.get_enum_member_by_text(Enum_Product_Category, text.upper())
|
||||
|
||||
|
||||
class Category(db.Model):
|
||||
id_category = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(255))
|
||||
description = db.Column(db.String(4000))
|
||||
display_order = db.Column(db.Integer)
|
||||
"""
|
||||
def __new__(cls, id, name, description, display_order):
|
||||
_m = 'Category.__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=4001, v_arg_type=v_arg_type)
|
||||
av.val_int(display_order, 'display_order', _m, v_arg_type=v_arg_type)
|
||||
return super(Category, cls).__new__(cls)
|
||||
"""
|
||||
def __init__(self): # , id, name, description, display_order):
|
||||
"""
|
||||
self.id_category = id
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.display_order = display_order
|
||||
"""
|
||||
self.products = []
|
||||
self.product_index = {}
|
||||
super().__init__()
|
||||
|
||||
def make_from_DB_product(query_row):
|
||||
category = Category()
|
||||
category.id_category = query_row[0]
|
||||
category.name = query_row[1]
|
||||
category.description = query_row[2]
|
||||
category.display_order = query_row[3]
|
||||
return category
|
||||
"""
|
||||
def key_product_index_from_ids_product_permutation(id_product, id_permutation):
|
||||
return f'{id_product},{"" if id_permutation is None else id_permutation}'
|
||||
def key_product_index_from_product(product):
|
||||
av.val_instance(product, 'product', 'Category.key_product_index_from_product', Product)
|
||||
return f'{product.id_product},{"" if product.id_permutation is None else product.id_permutation}'
|
||||
"""
|
||||
def get_index_product(self, product):
|
||||
return self.get_index_product_from_id(product.id_product)
|
||||
def get_index_product_from_id(self, id_product):
|
||||
try:
|
||||
return self.product_index[id_product]
|
||||
except:
|
||||
raise KeyError(f'product id: {id_product} not in product index keys: {self.product_index.keys()} with category id: {self.id_category}')
|
||||
def get_index_product_from_id_permutation(self, id_permutation):
|
||||
for product in self.products:
|
||||
try:
|
||||
index_permutation = product.get_index_permutation_from_id(id_permutation)
|
||||
return self.get_index_product(product)
|
||||
except:
|
||||
pass
|
||||
raise KeyError(f'permutation id: {id_permutation} not in category id: {self.id_category}')
|
||||
|
||||
def add_product(self, product):
|
||||
_m = 'Category.add_product'
|
||||
av.val_instance(product, 'product', _m, Product)
|
||||
# self.product_index.append(len(self.products))
|
||||
# self.product_index[Category.key_product_index_from_ids_product_permutation(product.id_product, product.id_permutation)] = len(self.products)
|
||||
try:
|
||||
self.get_index_product(product)
|
||||
raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.")
|
||||
except KeyError:
|
||||
self.product_index[product.id_product] = len(self.products)
|
||||
self.products.append(product)
|
||||
def add_permutation(self, permutation):
|
||||
_m = 'Category.add_permutation'
|
||||
av.val_instance(permutation, 'permutation', _m, Product_Permutation)
|
||||
# self.product_index.append(len(self.products))
|
||||
# self.product_index[Category.key_product_index_from_ids_product_permutation(product.id_product, product.id_permutation)] = len(self.products)
|
||||
index_product = self.get_index_product_from_id(permutation.id_product)
|
||||
# index_product = self.product_index[permutation.id_product]
|
||||
self.products[index_product].add_permutation(permutation)
|
||||
def add_variation(self, variation):
|
||||
av.val_instance(variation, 'variation', 'Category.add_variation', Variation)
|
||||
index_product = self.get_index_product_from_id(variation.id_product)
|
||||
self.products[index_product].add_variation(variation)
|
||||
def add_price(self, price):
|
||||
av.val_instance(price, 'price', 'Category.add_price', Price)
|
||||
index_product = self.get_index_product_from_id(price.id_product)
|
||||
self.products[index_product].add_price(price)
|
||||
def add_image(self, image):
|
||||
av.val_instance(image, 'image', 'Category.add_image', Image)
|
||||
index_product = self.get_index_product_from_id(image.id_product)
|
||||
self.products[index_product].add_image(image)
|
||||
def add_delivery_option(self, delivery_option):
|
||||
av.val_instance(delivery_option, 'delivery_option', 'Category.add_delivery_option', Delivery_Option)
|
||||
index_product = self.get_index_product_from_id(delivery_option.id_product)
|
||||
self.products[index_product].add_delivery_option(delivery_option)
|
||||
def add_discount(self, discount):
|
||||
av.val_instance(discount, 'discount', 'Category.add_discount', Discount)
|
||||
index_product = self.get_index_product_from_id(discount.id_product)
|
||||
self.products[index_product].add_discount(discount)
|
||||
|
||||
def get_all_variation_trees(self):
|
||||
for product in self.products:
|
||||
if product.has_variations:
|
||||
print(f'product with id:{product.id_product} has variations')
|
||||
product.get_variation_trees()
|
||||
|
||||
"""
|
||||
def index_product_from_ids_product_permutation(self, id_product, id_permutation):
|
||||
key = Category.key_product_index_from_ids_product_permutation(id_product, id_permutation)
|
||||
print(f'product_index: {self.product_index}')
|
||||
print(f'Key Error: {key}')
|
||||
try:
|
||||
return self.product_index[key]
|
||||
except KeyError:
|
||||
pass
|
||||
"""
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_category}
|
||||
name: {self.name}
|
||||
description: {self.description}
|
||||
display_order: {self.display_order}
|
||||
products: {self.products}
|
||||
'''
|
||||
|
||||
def get_permutation_first(self):
|
||||
if not (len(self.products) == 0):
|
||||
print(f'getting first permutation from product')
|
||||
return None if len(self.products) == 0 else self.products[0].get_permutation_selected()
|
||||
|
||||
|
||||
class Product_Category_Filters():
|
||||
category_ids: str # csv
|
||||
product_ids: str # csv
|
||||
|
||||
def __new__(cls, product_ids, product_categories):
|
||||
# Initialiser - validation
|
||||
_m = 'Product_Filters.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
# av.val_list_instances(product_ids, 'product_ids', _m, str, v_arg_type=v_arg_type)
|
||||
# av.val_list_instances(product_categories, 'product_categories', _m, Product_Category_Enum, v_arg_type=v_arg_type)
|
||||
av.val_str(product_ids, 'product_ids', _m, v_arg_type=v_arg_type)
|
||||
av.val_str(product_categories, 'product_categories', _m, v_arg_type=v_arg_type)
|
||||
return super(Product_Category_Filters, cls).__new__(cls)
|
||||
|
||||
def __init__(self, product_ids, product_categories):
|
||||
# Constructor
|
||||
self.ids = product_ids
|
||||
self.categories = product_categories
|
||||
|
||||
class Category_List():
|
||||
categories: list
|
||||
def __init__(self):
|
||||
self.categories = []
|
||||
def add_category(self, category):
|
||||
av.val_instance(category, 'category', 'Category_List.add_category', Category)
|
||||
self.categories.append(category)
|
||||
def get_index_category_from_id(self, id_category):
|
||||
for index_category in range(len(self.categories)):
|
||||
category = self.categories[index_category]
|
||||
if category.id_category == id_category:
|
||||
return index_category
|
||||
raise ValueError(f"{av.error_msg_str(id_category, 'id_category', 'Category_List.get_index_category_from_id', int)}\nID not in list")
|
||||
def get_index_category_from_id_permutation(self, id_permutation):
|
||||
for index_category in range(len(self.categories)):
|
||||
category = self.categories[index_category]
|
||||
try:
|
||||
index_product = category.get_index_product_from_id_permutation(id_permutation)
|
||||
return index_category
|
||||
except:
|
||||
pass
|
||||
raise ValueError(f"{av.error_msg_str(id_permutation, 'id_permutation', 'Category_List.get_index_category_from_id_permutation', int)}. Permutation ID not in list")
|
||||
def add_product(self, product):
|
||||
av.val_instance(product, 'product', 'Category_List.add_product', Product)
|
||||
index_category = self.get_index_category_from_id(product.id_category)
|
||||
self.categories[index_category].add_product(product)
|
||||
def add_permutation(self, permutation):
|
||||
av.val_instance(permutation, 'permutation', 'Category_List.add_permutation', Product_Permutation)
|
||||
index_category = self.get_index_category_from_id(permutation.id_category)
|
||||
self.categories[index_category].add_permutation(permutation)
|
||||
def add_variation(self, variation):
|
||||
av.val_instance(variation, 'variation', 'Category.add_variation', Variation)
|
||||
index_category = self.get_index_category_from_id(variation.id_category)
|
||||
self.categories[index_category].add_variation(variation)
|
||||
def add_price(self, price):
|
||||
av.val_instance(price, 'price', 'Category.add_price', Price)
|
||||
index_category = self.get_index_category_from_id(price.id_category)
|
||||
self.categories[index_category].add_price(price)
|
||||
def add_image(self, image):
|
||||
av.val_instance(image, 'image', 'Category.add_image', Image)
|
||||
index_category = self.get_index_category_from_id(image.id_category)
|
||||
self.categories[index_category].add_image(image)
|
||||
def add_delivery_option(self, delivery_option):
|
||||
av.val_instance(delivery_option, 'delivery_option', 'Category.add_delivery_option', Delivery_Option)
|
||||
index_category = self.get_index_category_from_id(delivery_option.id_category)
|
||||
self.categories[index_category].add_delivery_option(delivery_option)
|
||||
def add_discount(self, discount):
|
||||
av.val_instance(discount, 'discount', 'Category.add_discount', Discount)
|
||||
index_category = self.get_index_category_from_id(discount.id_category)
|
||||
self.categories[index_category].add_discount(discount)
|
||||
|
||||
def get_all_variation_trees(self):
|
||||
for category in self.categories:
|
||||
category.get_all_variation_trees()
|
||||
|
||||
def __repr__(self):
|
||||
return f'categories: {self.categories}'
|
||||
|
||||
def get_permutation_first(self):
|
||||
print(f'getting first permutation from category list')
|
||||
if not (len(self.categories) == 0):
|
||||
print(f'getting first permutation from category')
|
||||
return None if len(self.categories) == 0 else self.categories[0].get_permutation_first()
|
||||
|
||||
def get_count_categories(self):
|
||||
return len(self.categories)
|
||||
96
business_objects/currency.py
Normal file
96
business_objects/currency.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Business Object
|
||||
|
||||
Description:
|
||||
Business object for product
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
# 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):
|
||||
id_currency = db.Column(db.Integer, primary_key=True)
|
||||
code = db.Column(db.String)
|
||||
name = db.Column(db.String)
|
||||
symbol = db.Column(db.String)
|
||||
factor_from_GBP = db.Column(db.Float)
|
||||
display_order = db.Column(db.Integer)
|
||||
|
||||
def make_from_DB_currency(query_row):
|
||||
# _m = 'Currency.make_from_DB_currency'
|
||||
# v_arg_type = 'class attribute'
|
||||
currency = Currency()
|
||||
currency.id_currency = query_row[0]
|
||||
currency.code = query_row[1]
|
||||
currency.name = query_row[2]
|
||||
currency.symbol = query_row[3]
|
||||
currency.factor_from_GBP = query_row[4]
|
||||
currency.display_order = query_row[5]
|
||||
return currency
|
||||
"""
|
||||
def make_from_DB_product(query_row):
|
||||
_m = 'Currency.make_from_DB_product'
|
||||
v_arg_type = 'class attribute'
|
||||
currency = Currency()
|
||||
currency.id_permutation = query_row[0]
|
||||
currency.id_product = query_row[1]
|
||||
currency.id_category = query_row[2]
|
||||
currency.id_variation = query_row[3]
|
||||
return currency
|
||||
"""
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_currency}
|
||||
name: {self.name}
|
||||
code: {self.code}
|
||||
symbol: {self.symbol}
|
||||
factor from GBP: {self.factor_from_GBP}
|
||||
display_order: {self.display_order}
|
||||
'''
|
||||
115
business_objects/delivery_option.py
Normal file
115
business_objects/delivery_option.py
Normal file
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
# CLASSES
|
||||
"""
|
||||
class Delivery_Option():
|
||||
name: str
|
||||
delay_min: int # days
|
||||
delay_max: int
|
||||
quantity_min: float
|
||||
quantity_max: float
|
||||
regions: list # [Enum_Delivery_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_Delivery_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 make_from_DB_product(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}
|
||||
'''
|
||||
96
business_objects/delivery_region.py
Normal file
96
business_objects/delivery_region.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Delivery Region Business Object
|
||||
|
||||
Description:
|
||||
Business object for delivery region
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
# CLASSES
|
||||
class Enum_Delivery_Region(Enum):
|
||||
UK = 0
|
||||
|
||||
class Delivery_Region(db.Model):
|
||||
id_region = db.Column(db.Integer, primary_key=True)
|
||||
"""
|
||||
id_category = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_discount = db.Column(db.Integer)
|
||||
"""
|
||||
code = db.Column(db.String(50))
|
||||
name = db.Column(db.String(200))
|
||||
active = db.Column(db.Boolean)
|
||||
display_order = db.Column(db.Integer)
|
||||
"""
|
||||
def __new__(cls, id, id_category, id_product, id_discount, code, name, display_order):
|
||||
_m = 'Delivery_Region.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_int(id, 'id', _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(id_product, 'id_product', _m, 0, v_arg_type = v_arg_type)
|
||||
av.val_int(id_discount, 'id_discount', _m, v_arg_type = v_arg_type)
|
||||
av.val_str(code, 'code', _m, max_len = 50, v_arg_type = v_arg_type)
|
||||
av.val_str(name, 'name', _m, max_len = 100, v_arg_type = v_arg_type)
|
||||
av.val_int(display_order, 'display_order', _m, v_arg_type = v_arg_type)
|
||||
return super(Delivery_Region, cls).__new__(cls)
|
||||
|
||||
def __init__(self, id, id_category, id_product, id_discount, code, name, display_order):
|
||||
self.id_region = id
|
||||
self.id_category = id_category
|
||||
self.id_product = id_product
|
||||
self.id_discount = id_discount
|
||||
self.name = name
|
||||
self.code = code
|
||||
self.display_order = display_order
|
||||
"""
|
||||
def make_from_DB_product(query_row):
|
||||
region = Delivery_Region()
|
||||
region.id_region = query_row[0]
|
||||
region.name = query_row[1]
|
||||
region.code = query_row[2]
|
||||
# self.display_order = query_row[3]
|
||||
return region
|
||||
def make_from_DB_region(query_row):
|
||||
region = Delivery_Region()
|
||||
region.id_region = query_row[0]
|
||||
region.code = query_row[1]
|
||||
region.name = query_row[2]
|
||||
region.active = query_row[3]
|
||||
region.display_order = query_row[4]
|
||||
return region
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_region}
|
||||
name: {self.name}
|
||||
code: {self.code}
|
||||
active: {self.active}
|
||||
display_order: {self.display_order}
|
||||
'''
|
||||
|
||||
|
||||
|
||||
92
business_objects/discount.py
Normal file
92
business_objects/discount.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Discount Business Object
|
||||
|
||||
Description:
|
||||
Business object for discount
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
# CLASSES
|
||||
class Discount(db.Model):
|
||||
id_discount = db.Column(db.Integer, primary_key=True)
|
||||
id_category = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
code = db.Column(db.String(50))
|
||||
name = db.Column(db.String(200))
|
||||
multiplier = db.Column(db.Float)
|
||||
subtractor = db.Column(db.Float)
|
||||
apply_multiplier_first = db.Column(db.Boolean)
|
||||
quantity_min = db.Column(db.Integer)
|
||||
quantity_max = db.Column(db.Integer)
|
||||
date_start = db.Column(db.DateTime)
|
||||
date_end = db.Column(db.DateTime)
|
||||
codes_region = db.Column(db.String(4000))
|
||||
names_region = db.Column(db.String(4000))
|
||||
codes_currency = db.Column(db.String(4000))
|
||||
names_currency = db.Column(db.String(4000))
|
||||
display_order = db.Column(db.Integer)
|
||||
|
||||
def __init__(self):
|
||||
self.delivery_regions = []
|
||||
def make_from_DB_product(query_row):
|
||||
discount = Discount()
|
||||
discount.id_discount = query_row[0]
|
||||
discount.id_category = query_row[1]
|
||||
discount.id_product = query_row[2]
|
||||
discount.id_permutation = query_row[3]
|
||||
discount.code = query_row[4]
|
||||
discount.name = query_row[5]
|
||||
discount.multiplier = query_row[6]
|
||||
discount.subtractor = query_row[7]
|
||||
discount.apply_multiplier_first = query_row[8]
|
||||
discount.quantity_min = query_row[9]
|
||||
discount.quantity_max = query_row[10]
|
||||
discount.date_start = query_row[11]
|
||||
discount.date_end = query_row[12]
|
||||
discount.codes_region = query_row[13]
|
||||
discount.names_region = query_row[14]
|
||||
discount.codes_currency = query_row[15]
|
||||
discount.names_currency = query_row[16]
|
||||
discount.display_order = query_row[17]
|
||||
return discount
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_discount}
|
||||
id_category: {self.id_category}
|
||||
id_product: {self.id_product}
|
||||
name: {self.name}
|
||||
code: {self.code}
|
||||
multiplier: {self.multiplier}
|
||||
quantity_min: {self.quantity_min}
|
||||
quantity_max: {self.quantity_max}
|
||||
date_start: {self.date_start}
|
||||
date_end: {self.date_end}
|
||||
display_order: {self.display_order}
|
||||
'''
|
||||
|
||||
132
business_objects/image.py
Normal file
132
business_objects/image.py
Normal file
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Image Business Object
|
||||
|
||||
Description:
|
||||
Business object for product image
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
# CLASSES
|
||||
class Resolution_Level_Enum(Enum):
|
||||
THUMBNAIL = 0
|
||||
LOW = 1
|
||||
HIGH = 2
|
||||
FULL = 3
|
||||
|
||||
def text(self):
|
||||
return Resolution_Level_Enum.Resolution_Level_Enum_Text(self)
|
||||
|
||||
def Resolution_Level_Enum_Text(category):
|
||||
av.val_instance(category, 'category', 'Resolution_Level_Enum_Text', Resolution_Level_Enum)
|
||||
if category == Resolution_Level_Enum.THUMBNAIL:
|
||||
return 'Thumbnail'
|
||||
elif category == Resolution_Level_Enum.LOW:
|
||||
return 'Low resolution'
|
||||
elif category == Resolution_Level_Enum.HIGH:
|
||||
return 'High resolution'
|
||||
elif category == Resolution_Level_Enum.FULL:
|
||||
return 'Full resolution'
|
||||
else:
|
||||
return 'Unknown'
|
||||
|
||||
def get_member_by_text(text):
|
||||
for member in Resolution_Level_Enum.__members__.values():
|
||||
if member.name == text:
|
||||
return member
|
||||
return Resolution_Level_Enum.HIGH
|
||||
|
||||
|
||||
class Image(db.Model):
|
||||
id_image = 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)
|
||||
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 make_from_DB_product(query_row):
|
||||
_m = 'Image.make_from_DB_product'
|
||||
# print(f'image: {query_row}')
|
||||
image = Image()
|
||||
image.id_image = query_row[0]
|
||||
image.id_product = query_row[1]
|
||||
image.id_permutation = query_row[2]
|
||||
image.id_category = query_row[3]
|
||||
image.url = query_row[4]
|
||||
image.active = query_row[5]
|
||||
image.display_order = query_row[6]
|
||||
return image
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_image}
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
url: {self.url}
|
||||
display_order: {self.display_order}
|
||||
'''
|
||||
|
||||
|
||||
class Product_Image_Filters():
|
||||
product_id: int
|
||||
get_thumbnail: bool
|
||||
get_remaining_LQ: bool
|
||||
|
||||
def __new__(cls, product_id, get_thumbnail, get_remaining_LQ):
|
||||
# Initialiser - validation
|
||||
_m = 'Product_Filters.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_int(product_id, 'product_id', _m, v_arg_type=v_arg_type)
|
||||
av.val_bool(get_thumbnail, 'get_thumbnail', _m, v_arg_type=v_arg_type)
|
||||
av.val_bool(get_remaining_LQ, 'get_remaining_LQ', _m, v_arg_type=v_arg_type)
|
||||
return super(Product, cls).__new__(cls)
|
||||
|
||||
def __init__(self, product_id, get_thumbnail, get_remaining_LQ):
|
||||
# Constructor
|
||||
self.product_id = product_id
|
||||
self.get_thumbnail = get_thumbnail
|
||||
self.get_remaining_LQ = get_remaining_LQ
|
||||
|
||||
93
business_objects/order.py
Normal file
93
business_objects/order.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
# from lib import data_types
|
||||
from business_objects.product import Product
|
||||
from business_objects.delivery_option import Delivery_Option
|
||||
# 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():
|
||||
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 {
|
||||
'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}
|
||||
'''
|
||||
704
business_objects/product.py
Normal file
704
business_objects/product.py
Normal file
@@ -0,0 +1,704 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Business Object
|
||||
|
||||
Description:
|
||||
Business object for product
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
from business_objects.discount import Discount
|
||||
from business_objects.variation import Variation
|
||||
from business_objects.image import Image
|
||||
from business_objects.delivery_option import Delivery_Option
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from dataclasses import dataclass
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
# CLASSES
|
||||
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 Variation_Tree_Node():
|
||||
variation: Variation
|
||||
node_parent: None
|
||||
nodes_child: list
|
||||
def __init__(self):
|
||||
self.nodes_child = []
|
||||
def make_from_variation_and_node_parent(variation, node_parent):
|
||||
node = Variation_Tree_Node()
|
||||
node.variation = variation
|
||||
node.node_parent = node_parent
|
||||
return node
|
||||
def make_from_node_parent(node_parent):
|
||||
node = Variation_Tree_Node()
|
||||
node.node_parent = node_parent
|
||||
return node
|
||||
def add_child(self, node_child):
|
||||
self.nodes_child.append(node_child)
|
||||
def is_leaf(self):
|
||||
return (len(self.nodes_child) == 0)
|
||||
class Variation_Tree:
|
||||
node_root: Variation_Tree_Node
|
||||
def make_from_node_root(node_root):
|
||||
tree = Variation_Tree()
|
||||
tree.node_root = node_root
|
||||
return tree
|
||||
def get_variation_type_list(self):
|
||||
variation_types = []
|
||||
node = self.node_root
|
||||
at_leaf_node = node.is_leaf()
|
||||
while not at_leaf_node:
|
||||
variation_types.append(node.variation.name_variation_type)
|
||||
at_leaf_node = node.is_leaf()
|
||||
if not at_leaf_node:
|
||||
node = node.nodes_child[0]
|
||||
return variation_types
|
||||
def is_equal(self, tree):
|
||||
my_type_list = self.get_variation_type_list()
|
||||
sz_me = len(my_type_list)
|
||||
other_type_list = tree.get_variation_type_list()
|
||||
sz_other = len(other_type_list)
|
||||
is_equal = (sz_me == sz_other)
|
||||
if is_equal:
|
||||
for index_type in range(sz_me):
|
||||
if sz_me[index_type] != sz_other[index_type]:
|
||||
is_equal = False
|
||||
break
|
||||
return is_equal
|
||||
def make_from_product_permutation(product_permutation):
|
||||
depth_max = len(product_permutation.variations)
|
||||
node_root = Variation_Tree_Node.make_from_variation_and_node_parent(product_permutation.variations[0], None)
|
||||
node = node_root
|
||||
for depth in range(depth_max - 1):
|
||||
node = Variation_Tree_Node.make_from_variation_and_node_parent(product_permutation.variations[depth + 1], node)
|
||||
return Variation_Tree.make_from_node_root(node_root)
|
||||
|
||||
class Product(db.Model):
|
||||
id_product = db.Column(db.Integer, primary_key=True)
|
||||
id_category = db.Column(db.Integer)
|
||||
name = db.Column(db.String(255))
|
||||
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
|
||||
# has_variations: bool
|
||||
# index_permutation_selected: int
|
||||
|
||||
def __init__(self):
|
||||
self.permutations = []
|
||||
self.permutation_index = {}
|
||||
self.variation_trees = []
|
||||
self.index_permutation_selected = None
|
||||
self.has_variations = False
|
||||
super().__init__()
|
||||
self.form_basket_add = Form_Basket_Add()
|
||||
self.form_basket_edit = Form_Basket_Edit()
|
||||
|
||||
def make_from_DB_product(query_row):
|
||||
_m = 'Product.make_from_DB_product'
|
||||
v_arg_type = 'class attribute'
|
||||
product = Product()
|
||||
product.id_product = query_row[0]
|
||||
product.id_category = query_row[5]
|
||||
product.name = query_row[2]
|
||||
product.has_variations = av.input_bool(query_row[4], "has_variations", _m, v_arg_type=v_arg_type)
|
||||
product.display_order = query_row[17]
|
||||
product.can_view = av.input_bool(query_row[19], "can_view", _m, v_arg_type=v_arg_type)
|
||||
product.can_edit = av.input_bool(query_row[20], "can_edit", _m, v_arg_type=v_arg_type)
|
||||
product.can_admin = av.input_bool(query_row[21], "can_admin", _m, v_arg_type=v_arg_type)
|
||||
return product
|
||||
"""
|
||||
def make_from_permutation(permutation, has_variations = False):
|
||||
_m = 'Product.make_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_permutation(self, permutation):
|
||||
_m = 'Product.add_permutation'
|
||||
av.val_instance(permutation, 'permutation', _m, Product_Permutation)
|
||||
try:
|
||||
self.permutation_index[permutation.id_permutation]
|
||||
raise ValueError(f"{av.error_msg_str(permutation, 'permutation', _m, Product_Permutation)}\nPermutation ID already in product")
|
||||
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]
|
||||
print(f'setting selected permutation for product {self.id_product} to {self.index_permutation_selected}') # :\n{self.permutations[self.index_permutation_selected]}
|
||||
"""
|
||||
def make_from_permutations(permutations):
|
||||
_m = 'Product.make_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
|
||||
"""
|
||||
def get_variation_trees(self):
|
||||
for index_permutation in range(len(self.permutations)):
|
||||
variation_tree = Variation_Tree.make_from_product_permutation(self.permutations[index_permutation])
|
||||
found_variation_tree_match = False
|
||||
for index_tree in range(len(self.variation_trees)):
|
||||
if self.variation_trees[index_tree].is_equal(variation_tree):
|
||||
found_variation_tree_match = True
|
||||
break
|
||||
if not found_variation_tree_match:
|
||||
self.variation_trees.append(variation_tree)
|
||||
|
||||
def make_from_DB_Stripe_product(query_row):
|
||||
permutation = Product_Permutation.make_from_DB_Stripe_product(query_row)
|
||||
product = Product.make_from_permutation(permutation)
|
||||
return product
|
||||
|
||||
def make_from_DB_Stripe_price(query_row):
|
||||
permutation = Product_Permutation.make_from_DB_Stripe_price(query_row)
|
||||
product = Product.make_from_permutation(permutation)
|
||||
return product
|
||||
|
||||
def make_from_json(json_basket_item, key_id_product, key_id_permutation):
|
||||
permutation = Product_Permutation.make_from_json(json_basket_item, key_id_product, key_id_permutation)
|
||||
product = Product.make_from_permutation(permutation)
|
||||
return product
|
||||
|
||||
def get_permutation_selected(self):
|
||||
try:
|
||||
return self.permutations[self.index_permutation_selected]
|
||||
except:
|
||||
raise ValueError(f'list index {self.index_permutation_selected} out of range')
|
||||
def output_lead_time(self):
|
||||
return self.get_permutation_selected().output_lead_time()
|
||||
def output_delivery_date(self):
|
||||
return self.get_permutation_selected().output_delivery_date()
|
||||
def output_price(self, is_included_VAT):
|
||||
return self.get_permutation_selected().output_price(is_included_VAT)
|
||||
def output_price_VAT_incl(self):
|
||||
return self.get_permutation_selected().output_price(True)
|
||||
def output_price_VAT_excl(self):
|
||||
return self.get_permutation_selected().output_price(False)
|
||||
def get_price_local(self, is_included_VAT):
|
||||
if is_included_VAT:
|
||||
return self.get_price_local_VAT_incl()
|
||||
else:
|
||||
return self.get_price_local_VAT_excl()
|
||||
def get_price_local_VAT_incl(self):
|
||||
return self.get_permutation_selected().get_price_local_VAT_incl()
|
||||
def get_price_local_VAT_excl(self):
|
||||
return self.get_permutation_selected().get_price_local_VAT_excl()
|
||||
def get_quantity_min(self):
|
||||
return self.get_permutation_selected().quantity_min
|
||||
def get_id_permutation(self):
|
||||
return self.get_permutation_selected().id_permutation
|
||||
def get_image_from_index(self, index_image):
|
||||
return self.get_permutation_selected().images[index_image]
|
||||
def get_name(self):
|
||||
return self.get_permutation_selected().name
|
||||
def get_description(self):
|
||||
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}
|
||||
id_category: {self.id_category}
|
||||
name: {self.name}
|
||||
display_order: {self.display_order}
|
||||
can_view: {self.can_view}
|
||||
can_edit: {self.can_edit}
|
||||
can_admin: {self.can_admin}
|
||||
has_variations: {self.has_variations}
|
||||
permutations: {self.permutations}
|
||||
variation trees: {self.variation_trees}
|
||||
'''
|
||||
"""
|
||||
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_variation(self, variation):
|
||||
av.val_instance(variation, 'variation', 'Product.add_variation', Variation)
|
||||
# print(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_variation(variation)
|
||||
def add_price(self, price):
|
||||
av.val_instance(price, 'price', 'Product.add_price', Price)
|
||||
index_permutation = self.permutation_index[price.id_permutation] # self.get_index_permutation_from_id(price.id_permutation)
|
||||
self.permutations[index_permutation].add_price(price)
|
||||
def add_image(self, image):
|
||||
av.val_instance(image, 'image', 'Product.add_image', Image)
|
||||
index_permutation = self.permutation_index[image.id_permutation] # self.get_index_permutation_from_id(image.id_permutation)
|
||||
self.permutations[index_permutation].add_image(image)
|
||||
def add_delivery_option(self, delivery_option):
|
||||
av.val_instance(delivery_option, 'delivery_option', 'Product.add_delivery_option', Delivery_Option)
|
||||
index_permutation = self.permutation_index[delivery_option.id_permutation] # self.get_index_permutation_from_id(delivery_option.id_permutation)
|
||||
self.permutations[index_permutation].add_delivery_option(delivery_option)
|
||||
def add_discount(self, discount):
|
||||
av.val_instance(discount, 'discount', 'Product.add_discount', Discount)
|
||||
index_permutation = self.permutation_index[discount.id_permutation] # self.get_index_permutation_from_id(discount.id_permutation)
|
||||
self.permutations[index_permutation].add_discount(discount)
|
||||
|
||||
|
||||
class Product_Permutation(db.Model):
|
||||
id_product = db.Column(db.Integer, primary_key=True)
|
||||
id_permutation = 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)
|
||||
# price_GBP_min = db.Column(db.Float)
|
||||
has_variations = db.Column(db.Boolean)
|
||||
id_category = db.Column(db.Integer)
|
||||
latency_manufacture = 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(100))
|
||||
is_subscription = db.Column(db.Boolean)
|
||||
name_recurrence_interval = db.Column(db.String(255))
|
||||
name_plural_recurrence_interval = db.Column(db.String(256))
|
||||
count_recurrence_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
|
||||
# is_unavailable_in_currency_or_region: bool
|
||||
# is_available: bool
|
||||
|
||||
def __init__(self):
|
||||
self.variations = []
|
||||
self.variation_index = {}
|
||||
self.prices = []
|
||||
self.price_index = {}
|
||||
self.images = []
|
||||
self.image_index = {}
|
||||
self.delivery_options = []
|
||||
self.delivery_option_index = {}
|
||||
self.discounts = []
|
||||
self.discount_index = {}
|
||||
super().__init__()
|
||||
self.form_basket_add = Form_Basket_Add()
|
||||
self.form_basket_edit = Form_Basket_Edit()
|
||||
self.is_unavailable_in_currency_or_region = False
|
||||
self.is_available = True
|
||||
|
||||
def make_from_DB_product(query_row):
|
||||
_m = 'Product_Permutation.make_from_DB_product'
|
||||
v_arg_type = 'class attribute'
|
||||
print(f'query_row: {query_row}')
|
||||
permutation = Product_Permutation()
|
||||
permutation.id_product = query_row[0]
|
||||
permutation.id_permutation = query_row[1]
|
||||
# permutation.name = query_row[2]
|
||||
permutation.description = query_row[3]
|
||||
# permutation.price_GBP_full = query_row[4]
|
||||
# permutation.price_GBP_min = query_row[5]
|
||||
permutation.has_variations = query_row[4]
|
||||
permutation.id_category = query_row[5]
|
||||
permutation.latency_manufacture = query_row[6]
|
||||
permutation.quantity_min = query_row[7]
|
||||
permutation.quantity_max = query_row[8]
|
||||
permutation.quantity_step = query_row[9]
|
||||
permutation.quantity_stock = query_row[10]
|
||||
permutation.id_stripe_product = query_row[11]
|
||||
permutation.is_subscription = av.input_bool(query_row[12], "is_subscription", _m, v_arg_type=v_arg_type)
|
||||
permutation.name_recurrence_interval = query_row[13]
|
||||
permutation.name_plural_recurrence_interval = query_row[14]
|
||||
permutation.count_recurrence_interval = query_row[15]
|
||||
permutation.display_order = query_row[18]
|
||||
permutation.can_view = av.input_bool(query_row[19], "can_view", _m, v_arg_type=v_arg_type)
|
||||
permutation.can_edit = av.input_bool(query_row[20], "can_edit", _m, v_arg_type=v_arg_type)
|
||||
permutation.can_admin = av.input_bool(query_row[21], "can_admin", _m, v_arg_type=v_arg_type)
|
||||
return permutation
|
||||
|
||||
def make_from_DB_Stripe_product(query_row):
|
||||
_m = 'Product_Permutation.make_from_DB_Stripe_product'
|
||||
v_arg_type = 'class attribute'
|
||||
permutation = Product_Permutation()
|
||||
permutation.id_product = query_row[0]
|
||||
# permutation.name = query_row[1]
|
||||
permutation.description = query_row[2]
|
||||
return permutation
|
||||
|
||||
def make_from_DB_Stripe_price(query_row):
|
||||
_m = 'Product_Permutation.make_from_DB_Stripe_price'
|
||||
v_arg_type = 'class attribute'
|
||||
permutation = Product_Permutation()
|
||||
permutation.id_product = query_row[0]
|
||||
# permutation.price_GBP_full = query_row[1]
|
||||
permutation.id_stripe_product = query_row[2]
|
||||
permutation.is_subscription = av.input_bool(query_row[3], "is_subscription", _m, v_arg_type=v_arg_type)
|
||||
permutation.name_recurrence_interval = query_row[4]
|
||||
permutation.count_recurrence_interval = query_row[5]
|
||||
return permutation
|
||||
|
||||
def make_from_json(json_basket_item, key_id_product, key_id_permutation):
|
||||
_m = 'Product_Permutation.make_from_json'
|
||||
v_arg_type = 'class attribute'
|
||||
permutation = Product_Permutation()
|
||||
permutation.id_product = json_basket_item[key_id_product]
|
||||
permutation.id_permutation = json_basket_item[key_id_permutation]
|
||||
return permutation
|
||||
|
||||
def get_price(self):
|
||||
return self.prices[0]
|
||||
def get_price_local_VAT_incl(self):
|
||||
price = self.get_price()
|
||||
return price.value_local_VAT_incl
|
||||
def get_price_local_VAT_excl(self):
|
||||
price = self.get_price()
|
||||
return price.value_local_VAT_excl
|
||||
|
||||
def output_lead_time(self):
|
||||
return '1 day' if self.latency_manufacture == 1 else f'{self.latency_manufacture} days'
|
||||
|
||||
def output_delivery_date(self):
|
||||
return (datetime.now() + timedelta(days=self.latency_manufacture)).strftime('%A, %d %B %Y')
|
||||
|
||||
def output_price(self, is_included_VAT):
|
||||
if self.is_unavailable_in_currency_or_region:
|
||||
return 'Not available in currency and region'
|
||||
if not self.is_available:
|
||||
return 'Not available'
|
||||
price = self.get_price()
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
if is_included_VAT:
|
||||
return f'{price.symbol_currency} {locale.format_string("%d", price.value_local_VAT_incl, grouping=True)}'
|
||||
else:
|
||||
return f'{price.symbol_currency} {locale.format_string("%d", price.value_local_VAT_excl, grouping=True)}'
|
||||
def output_currency(self):
|
||||
if not self.is_available:
|
||||
return ''
|
||||
price = self.get_price()
|
||||
return price.code_currency
|
||||
"""
|
||||
def output_price_VAT_incl(self):
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
return locale.format_string("%d", self.price_GBP_VAT_incl, grouping=True)
|
||||
def output_price_VAT_excl(self):
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
return locale.format_string("%d", self.price_GBP_VAT_excl, 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_Permutation
|
||||
id_product: {self.id_product}
|
||||
id_permutation: {self.id_permutation}
|
||||
description: {self.description}
|
||||
id_category: {self.id_category}
|
||||
latency_manufacture: {self.latency_manufacture}
|
||||
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}
|
||||
is_subscription: {self.is_subscription}
|
||||
name_recurrence_interval: {self.name_recurrence_interval}
|
||||
name_plural_recurrence_interval: {self.name_plural_recurrence_interval}
|
||||
count_recurrence_interval: {self.count_recurrence_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}
|
||||
prices: {self.prices}
|
||||
'''
|
||||
"""
|
||||
price_GBP_full: {self.price_GBP_full}
|
||||
price_GBP_min: {self.price_GBP_min}
|
||||
"""
|
||||
|
||||
def add_variation(self, variation):
|
||||
_m = 'Product_Permutation.add_variation'
|
||||
av.val_instance(variation, 'variation', _m, Variation)
|
||||
try:
|
||||
self.variation_index[variation.id_variation]
|
||||
raise ValueError(f"{av.error_msg_str(variation, 'variation', _m, Variation)}\nVariation already in product.")
|
||||
except KeyError:
|
||||
self.variation_index[variation.id_variation] = len(self.variations)
|
||||
self.variations.append(variation)
|
||||
def add_price(self, price):
|
||||
_m = 'Product_Permutation.add_price'
|
||||
av.val_instance(price, 'price', _m, Price)
|
||||
try:
|
||||
self.price_index[price.display_order]
|
||||
raise ValueError(f"{av.error_msg_str(price, 'price', _m, Price)}\nPrice already in product.")
|
||||
except KeyError:
|
||||
self.price_index[price.display_order] = len(self.prices)
|
||||
self.prices.append(price)
|
||||
def add_image(self, image):
|
||||
_m = 'Product_Permutation.add_image'
|
||||
av.val_instance(image, 'image', _m, Image)
|
||||
try:
|
||||
self.image_index[image.id_image]
|
||||
raise ValueError(f"{av.error_msg_str(image, 'image', _m, Image)}\nImage already in product.")
|
||||
except KeyError:
|
||||
self.image_index[image.id_image] = len(self.images)
|
||||
self.images.append(image)
|
||||
def add_delivery_option(self, delivery_option):
|
||||
_m = 'Product_Permutation.add_delivery_option'
|
||||
av.val_instance(delivery_option, 'delivery_option', _m, Delivery_Option)
|
||||
try:
|
||||
self.delivery_option_index[delivery_option.id_option]
|
||||
raise ValueError(f"{av.error_msg_str(delivery_option, 'delivery_option', _m, Delivery_Option)}\nDelivery_Option already in product.")
|
||||
except KeyError:
|
||||
self.delivery_option_index[delivery_option.id_option] = len(self.delivery_options)
|
||||
self.delivery_options.append(delivery_option)
|
||||
def add_discount(self, discount):
|
||||
_m = 'Product_Permutation.add_discount'
|
||||
av.val_instance(discount, 'discount', _m, Discount)
|
||||
try:
|
||||
self.discount_index[discount.display_order]
|
||||
raise ValueError(f"{av.error_msg_str(discount, 'discount', _m, Discount)}\nDiscount already in product.")
|
||||
except KeyError:
|
||||
self.discount_index[discount.display_order] = len(self.discounts)
|
||||
self.discounts.append(discount)
|
||||
|
||||
def get_image_from_index(self, index_image):
|
||||
try:
|
||||
return self.images[index_image]
|
||||
except:
|
||||
raise IndexError(f"Invalid image index: {index_image}")
|
||||
|
||||
def get_price_from_code_currency(self, code_currency):
|
||||
for price in self.prices:
|
||||
if price.code_currency == code_currency:
|
||||
return price
|
||||
|
||||
"""
|
||||
class Product_Filters():
|
||||
ids: str # csv
|
||||
categories: str # csv
|
||||
|
||||
def __new__(cls, product_ids, product_categories):
|
||||
# Initialiser - validation
|
||||
_m = 'Product_Filters.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
# av.val_list_instances(product_ids, 'product_ids', _m, str, v_arg_type=v_arg_type)
|
||||
# av.val_list_instances(product_categories, 'product_categories', _m, Product_Category_Enum, v_arg_type=v_arg_type)
|
||||
av.val_str(product_ids, 'product_ids', _m, v_arg_type=v_arg_type)
|
||||
av.val_str(product_categories, 'product_categories', _m, v_arg_type=v_arg_type)
|
||||
return super(Product, cls).__new__(cls)
|
||||
|
||||
def __init__(self, product_ids, product_categories):
|
||||
# Constructor
|
||||
self.ids = product_ids
|
||||
self.categories = product_categories
|
||||
|
||||
class Price():
|
||||
product: Product
|
||||
currency: Currency_Enum
|
||||
|
||||
def make_from_product_currency(product, code_currency):
|
||||
name_method = 'make_from_product_currency'
|
||||
av.val_instance(product, 'product', name_method, Product)
|
||||
price = Price()
|
||||
price.product = product
|
||||
price.currency = Currency_Enum.get_member_by_text(code_currency)
|
||||
"""
|
||||
|
||||
class Price(db.Model):
|
||||
id_price = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
id_currency = db.Column(db.Integer)
|
||||
code_currency = db.Column(db.String)
|
||||
name_currency = db.Column(db.String)
|
||||
symbol_currency = db.Column(db.String)
|
||||
id_region = db.Column(db.Integer)
|
||||
value_local_VAT_incl = db.Column(db.Float)
|
||||
value_local_VAT_excl = db.Column(db.Float)
|
||||
display_order = db.Column(db.Float, primary_key=True)
|
||||
|
||||
def make_from_DB_product(query_row):
|
||||
_m = 'Price.make_from_DB_product'
|
||||
price = Price()
|
||||
price.id_price = query_row[0]
|
||||
price.id_permutation = query_row[1]
|
||||
price.id_product = query_row[2]
|
||||
price.id_category = query_row[3]
|
||||
price.id_currency = query_row[4]
|
||||
price.code_currency = query_row[5]
|
||||
price.name_currency = query_row[6]
|
||||
price.symbol_currency = query_row[7]
|
||||
price.id_region = query_row[8]
|
||||
price.value_local_VAT_incl = query_row[9]
|
||||
price.value_local_VAT_excl = query_row[10]
|
||||
price.display_order = query_row[11]
|
||||
return price
|
||||
|
||||
def __repr__(self):
|
||||
return f'''Price
|
||||
id: {self.id_price}
|
||||
id_permutation: {self.id_permutation}
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
id_currency: {self.id_currency}
|
||||
code_currency: {self.code_currency}
|
||||
name_currency: {self.name_currency}
|
||||
symbol_currency: {self.symbol_currency}
|
||||
id_region: {self.id_region}
|
||||
value_local (VAT incl): {self.value_local_VAT_incl}
|
||||
value_local (VAT excl): {self.value_local_VAT_excl}
|
||||
display_order (UID): {self.display_order}
|
||||
'''
|
||||
"""
|
||||
class Permutation_Variation_Link(db.Model):
|
||||
id_permutation = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
id_variation = db.Column(db.Integer)
|
||||
|
||||
def make_from_DB_product(query_row):
|
||||
_m = 'Permutation_Variation_Link.make_from_DB_product'
|
||||
v_arg_type = 'class attribute'
|
||||
link = Permutation_Variation_Link()
|
||||
link.id_permutation = query_row[0]
|
||||
link.id_product = query_row[1]
|
||||
link.id_category = query_row[2]
|
||||
link.id_variation = query_row[3]
|
||||
return link
|
||||
"""
|
||||
|
||||
@dataclass
|
||||
class Product_Filters():
|
||||
id_user: str
|
||||
get_all_category: bool
|
||||
ids_category: str
|
||||
get_inactive_category: bool
|
||||
get_all_product: bool
|
||||
ids_product: str
|
||||
get_inactive_product: bool
|
||||
get_first_product_only: bool
|
||||
get_all_permutation: bool
|
||||
ids_permutation: str
|
||||
get_inactive_permutation: bool
|
||||
get_all_image: bool
|
||||
ids_image: str
|
||||
get_inactive_image: bool
|
||||
get_first_image_only: bool
|
||||
get_all_region: bool
|
||||
ids_region: str
|
||||
get_inactive_region: bool
|
||||
get_all_currency: bool
|
||||
ids_currency: str
|
||||
get_inactive_currency: bool
|
||||
get_all_discount: bool
|
||||
ids_discount: str
|
||||
get_inactive_discount: bool
|
||||
def to_json(self):
|
||||
return {
|
||||
'a_id_user': self.id_user,
|
||||
'a_get_all_category': self.get_all_category,
|
||||
'a_ids_category': self.ids_category,
|
||||
'a_get_inactive_category': self.get_inactive_category,
|
||||
'a_get_all_product': self.get_all_product,
|
||||
'a_ids_product': self.ids_product,
|
||||
'a_get_inactive_product': self.get_inactive_product,
|
||||
'a_get_first_product_only': self.get_first_product_only,
|
||||
'a_get_all_permutation': self.get_all_permutation,
|
||||
'a_ids_permutation': self.ids_permutation,
|
||||
'a_get_inactive_permutation': self.get_inactive_permutation,
|
||||
'a_get_all_image': self.get_all_image,
|
||||
'a_ids_image': self.ids_image,
|
||||
'a_get_inactive_image': self.get_inactive_image,
|
||||
'a_get_first_image_only': self.get_first_image_only,
|
||||
'a_get_all_delivery_region': self.get_all_region,
|
||||
'a_ids_delivery_region': self.ids_region,
|
||||
'a_get_inactive_delivery_region': self.get_inactive_region,
|
||||
'a_get_all_currency': self.get_all_currency,
|
||||
'a_ids_currency': self.ids_currency,
|
||||
'a_get_inactive_currency': self.get_inactive_currency,
|
||||
'a_get_all_discount': self.get_all_discount,
|
||||
'a_ids_discount': self.ids_discount,
|
||||
'a_get_inactive_discount': self.get_inactive_discount
|
||||
}
|
||||
65
business_objects/sql_error.py
Normal file
65
business_objects/sql_error.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: SQL Error Business Object
|
||||
|
||||
Description:
|
||||
Business object for SQL errors
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
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)
|
||||
code = db.Column(db.String(50))
|
||||
msg = db.Column(db.String(4000))
|
||||
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 make_from_DB_record(record):
|
||||
error = SQL_Error()
|
||||
error.display_order = record[0]
|
||||
error.code = record[1]
|
||||
error.msg = record[2]
|
||||
error.name = record[3]
|
||||
error.description = record[4]
|
||||
return error
|
||||
164
business_objects/stripe.py
Normal file
164
business_objects/stripe.py
Normal file
@@ -0,0 +1,164 @@
|
||||
"""
|
||||
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 import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
db = SQLAlchemy()
|
||||
|
||||
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)
|
||||
print(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_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)
|
||||
94
business_objects/variation.py
Normal file
94
business_objects/variation.py
Normal file
@@ -0,0 +1,94 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Variation Business Object
|
||||
|
||||
Description:
|
||||
Business object for product variation
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
# external
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
db = SQLAlchemy()
|
||||
|
||||
|
||||
# CLASSES
|
||||
class Variation(db.Model):
|
||||
id_variation = 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_variation_type = db.Column(db.String(50))
|
||||
name_variation_type = db.Column(db.String(255))
|
||||
code_variation = db.Column(db.String(50))
|
||||
name_variation = db.Column(db.String(255))
|
||||
display_order = db.Column(db.Integer)
|
||||
|
||||
"""
|
||||
def __new__(cls, id, id_product, id_category, name_type, code_type, name, code, display_order):
|
||||
_m = 'Variation.__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(code_type, 'code_type', _m, max_len=50, v_arg_type=v_arg_type)
|
||||
av.val_str(name_type, 'name_type', _m, max_len=256, v_arg_type=v_arg_type)
|
||||
av.val_str(code, 'code', _m, max_len=50, v_arg_type=v_arg_type)
|
||||
av.val_str(name, 'name', _m, max_len=256, v_arg_type=v_arg_type)
|
||||
av.val_int(display_order, 'display_order', _m, v_arg_type=v_arg_type)
|
||||
return super(Variation, cls).__new__(cls)
|
||||
|
||||
def __init__(self, id, id_product, id_category, name_type, code_type, name, code, display_order):
|
||||
self.id_variation = id
|
||||
self.id_product = id_product
|
||||
self.id_category = id_category
|
||||
self.name_variation_type = name_type
|
||||
self.code_variation_type = code_type
|
||||
self.name_variation = name
|
||||
self.code_variation = code
|
||||
self.display_order = display_order
|
||||
super().__init__()
|
||||
"""
|
||||
def make_from_DB_product(query_row):
|
||||
variation = Variation()
|
||||
variation.id_variation = query_row[0]
|
||||
variation.id_product = query_row[1]
|
||||
variation.id_permutation = query_row[2]
|
||||
variation.id_category = query_row[3]
|
||||
variation.code_variation_type = query_row[4]
|
||||
variation.name_variation_type = query_row[5]
|
||||
variation.code_variation = query_row[6]
|
||||
variation.name_variation = query_row[7]
|
||||
variation.display_order = query_row[8]
|
||||
return variation
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_variation}
|
||||
id_product: {self.id_product}
|
||||
id_permutation: {self.id_permutation}
|
||||
id_category: {self.id_category}
|
||||
code_variation_type: {self.code_variation_type}
|
||||
name_variation_type: {self.name_variation_type}
|
||||
code_variation: {self.code_variation}
|
||||
name_variation: {self.name_variation}
|
||||
display_order: {self.display_order}
|
||||
'''
|
||||
Reference in New Issue
Block a user