1. Refactoring form objects and database objects to use inheritance and abstract base class for consistency and reduced redundancy.\n2. Contact us page button links updated to resolve error of missing link causing page refresh instead of expected functionality.

This commit is contained in:
2024-09-10 12:09:50 +01:00
parent b3e801e1ec
commit 2d55fe6239
709 changed files with 5158 additions and 1512 deletions

View File

@@ -14,6 +14,7 @@ Business object for product
import lib.argument_validation as av
from lib import data_types
from forms.forms import Form_Basket_Add, Form_Basket_Edit, Form_Filters_Permutation
from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
from business_objects.store.delivery_option import Delivery_Option
from business_objects.store.discount import Discount
from business_objects.store.image import Image
@@ -24,6 +25,7 @@ from business_objects.store.stock_item import Stock_Item
from business_objects.store.product_variation import Product_Variation
from business_objects.store.product_variation_tree import Product_Variation_Tree
from extensions import db
from forms.store.product import Form_Filters_Product
# external
from dataclasses import dataclass
from typing import ClassVar, List
@@ -49,7 +51,7 @@ class Enum_Status_Stock(Enum):
return data_types.get_enum_member_by_text(Enum_Status_Stock, text.upper())
"""
class Product(db.Model, Store_Base):
class Product(SQLAlchemy_ABC, Store_Base):
FLAG_NAME: ClassVar[str] = 'name-product'
FLAG_DISPLAY_ORDER: ClassVar[str] = 'display-order-product'
FLAG_CAN_VIEW: ClassVar[str] = 'can-view-product'
@@ -83,9 +85,10 @@ class Product(db.Model, Store_Base):
Store_Base.__init__(self)
self.form_basket_add = Form_Basket_Add()
self.form_basket_edit = Form_Basket_Edit()
self.name_access_level_required = None
def from_DB_product(query_row):
_m = 'Product.from_DB_product'
def from_DB_get_many_product_catalogue(query_row):
_m = 'Product.from_DB_get_many_product_catalogue'
v_arg_type = 'class attribute'
product = Product()
product.id_product = query_row[0]
@@ -93,11 +96,12 @@ class Product(db.Model, Store_Base):
product.name = query_row[2]
product.has_variations = av.input_bool(query_row[3], "has_variations", _m, v_arg_type=v_arg_type)
product.id_access_level_required = query_row[4]
product.active = av.input_bool(query_row[5], "active", _m, v_arg_type=v_arg_type)
product.display_order = query_row[6]
product.can_view = av.input_bool(query_row[7], "can_view", _m, v_arg_type=v_arg_type)
product.can_edit = av.input_bool(query_row[8], "can_edit", _m, v_arg_type=v_arg_type)
product.can_admin = av.input_bool(query_row[9], "can_admin", _m, v_arg_type=v_arg_type)
product.name_access_level_required = query_row[5]
product.active = av.input_bool(query_row[6], "active", _m, v_arg_type=v_arg_type)
product.display_order = query_row[7]
product.can_view = av.input_bool(query_row[8], "can_view", _m, v_arg_type=v_arg_type)
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):
@@ -117,8 +121,8 @@ class Product(db.Model, Store_Base):
# product.get_variation_trees()
return product
"""
def add_permutation(self, permutation):
_m = 'Product.add_permutation'
def add_product_permutation(self, permutation):
_m = 'Product.add_product_permutation'
av.val_instance(permutation, 'permutation', _m, Product_Permutation)
try:
self.permutation_index[permutation.id_permutation]
@@ -159,7 +163,8 @@ class Product(db.Model, Store_Base):
def get_variation_trees(self):
self.variation_trees = []
for index_permutation in range(len(self.permutations)):
variation_tree = Product_Variation_Tree.from_product_permutation(self.permutations[index_permutation])
permutation = self.permutations[index_permutation]
variation_tree = permutation.variation_tree # Product_Variation_Tree.from_product_permutation(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):
@@ -245,27 +250,27 @@ class Product(db.Model, Store_Base):
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', Product_Variation)
def add_product_variation(self, variation):
av.val_instance(variation, 'variation', 'Product.add_product_variation', Product_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', Product_Price)
self.permutations[index_permutation].add_product_variation(variation)
def add_product_price(self, price):
av.val_instance(price, 'price', 'Product.add_product_price', Product_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)
self.permutations[index_permutation].add_product_price(price)
def add_product_image(self, image):
av.val_instance(image, 'image', 'Product.add_product_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)
self.permutations[index_permutation].add_product_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)
def add_product_price_discount(self, discount):
av.val_instance(discount, 'discount', 'Product.add_product_price_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)
self.permutations[index_permutation].add_product_price_discount(discount)
def add_stock_item(self, stock_item):
av.val_instance(stock_item, 'stock_item', 'Product.add_stock_item', Stock_Item)
index_permutation = self.permutation_index[stock_item.id_permutation]
@@ -279,7 +284,7 @@ class Product(db.Model, Store_Base):
if permutation.is_available():
return True
return False
def to_list_rows_permutation(self):
def to_permutation_row_list(self):
list_rows = []
for permutation in self.permutations:
list_rows.append(permutation.to_row_permutation())
@@ -317,6 +322,35 @@ class Product(db.Model, Store_Base):
self.ATTR_ID_PRODUCT_PERMUTATION: [permutation.to_json() for permutation in self.permutations],
self.FLAG_VARIATION_TREES: [tree.to_json() for tree in self.variation_trees]
}
def to_json_option(self):
return {
'value': self.id_product,
'text': self.name
}
def get_variation_types_unique(self):
list_types = []
for tree in self.variation_trees:
for type in tree.get_types_unique():
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
"""
@dataclass
class Filters_Product():
@@ -386,7 +420,44 @@ class Filters_Product():
}
@staticmethod
def from_form(form):
def from_form_filters_product(form):
# if not (form is Form_Filters_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
av.val_instance(form, 'form', 'Filters_Product.from_form', 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", "Filters_Product.from_form_filters_product")
active = av.input_bool(form.active.data, "active", "Filters_Product.from_form_filters_product")
return Filters_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,
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 Form_Filters_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
av.val_instance(form, 'form', 'Filters_Product.from_form', Form_Filters_Permutation)
has_category_filter = not (form.id_category.data == '0' or form.id_category.data == '')
@@ -494,7 +565,7 @@ class Filters_Product():
def from_filters_product_category(cls, filters_category):
return cls(
get_all_product_category = True,
get_inactive_product_category = filters_category.active_only,
get_inactive_product_category = filters_category.active,
ids_product_category = '',
get_all_product = True,
get_inactive_product = False,
@@ -506,4 +577,234 @@ class Filters_Product():
get_inactive_image = False,
ids_image = '',
get_products_quantity_stock_below_min = False
)
class Filters_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, **kwargs):
super().__init__(**kwargs)
def to_json(self):
return {
'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 Form_Filters_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
av.val_instance(form, 'form', 'Filters_Product.from_form', 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", "Filters_Product.from_form_filters_product")
active = av.input_bool(form.active.data, "active", "Filters_Product.from_form_filters_product")
return Filters_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,
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 Form_Filters_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
av.val_instance(form, 'form', 'Filters_Product.from_form', Form_Filters_Permutation)
has_category_filter = not (form.id_category.data == '0' or form.id_category.data == '')
has_product_filter = not (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", "Filters_Product.from_form")
print(f'form question: {type(form.is_out_of_stock)}\nbool interpretted: {get_permutations_stock_below_min}\type form: {type(form)}')
return Filters_Product(
get_all_product_category = not has_category_filter,
get_inactive_product_category = False,
# get_first_product_category_only = False,
ids_product_category = form.id_category.data,
get_all_product = not has_product_filter,
get_inactive_product = False,
# get_first_product_only = False,
ids_product = form.id_product.data,
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
)
@staticmethod
def get_default():
return Filters_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
)
@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
)