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 c9dda91dc9
commit 6b730bf8e7
709 changed files with 5158 additions and 1512 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,73 @@
"""
Project: PARTS Website
Author: Edward Middleton-Smith
Precision And Research Technology Systems Limited
Technology: Business Objects
Feature: Database Base Business Objects
Description:
Abstract business object for database objects
"""
# internal
# from helpers.DEPRECATED.helper_abc import Interface_ABC
from extensions import db
import lib.argument_validation as av
# external
from typing import ClassVar
from abc import abstractmethod, ABCMeta
from pydantic import BaseModel
from sqlalchemy.ext.declarative import DeclarativeMeta
# from flask_sqlalchemy import SQLAlchemy
class Get_Many_Parameters_Base(BaseModel, metaclass=ABCMeta):
def __init__(self, **kwargs):
super().__init__(**kwargs)
@classmethod
@abstractmethod
def get_default(cls):
pass
@abstractmethod
def to_json(self):
pass
@classmethod
@abstractmethod
def from_json(cls, json):
pass
"""
@classmethod
@abstractmethod
def from_form(cls, form):
pass
"""
# db = SQLAlchemy()
# Base = declarative_base()
class SQLAlchemy_ABCMeta(db.Model.__class__, ABCMeta):
pass
class SQLAlchemy_ABC(db.Model, metaclass=SQLAlchemy_ABCMeta):
__abstract__ = True
# id = db.Column(db.Integer, primary_key=True)
def __init__(self):
pass
def __repr__(self):
pass
def to_json(self):
pass
@classmethod
def from_json(cls, json):
pass
def to_json_option(self):
pass
def to_temporary_record(self):
pass
def to_object_with_missing_attributes(self, excluded_attributes):
return {
column.name: getattr(self, column.name)
for column in self.__table__.columns
if column.name not in excluded_attributes
}

View File

@@ -0,0 +1,95 @@
"""
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
"""
# internal
import lib.argument_validation as av
from business_objects.store.store_base import Store_Base
from extensions import db
# external
from pydantic import BaseModel
from typing import ClassVar
class Access_Level(db.Model, Store_Base):
__tablename__ = 'Shop_Access_Level_Temp'
id_access_level = db.Column(db.Integer, primary_key=True)
code = db.Column(db.String(50))
name = db.Column(db.String(255))
description = db.Column(db.String(4000))
priority = db.Column(db.Integer)
display_order = db.Column(db.Integer)
active = db.Column(db.Boolean)
created_on = db.Column(db.DateTime)
created_by = db.Column(db.Integer)
def __init__(self):
super().__init__()
Store_Base.__init__(self)
def from_DB_access_level(query_row):
access_level = Access_Level()
access_level.id_access_level = query_row[0]
access_level.code = query_row[1]
access_level.name = query_row[2]
access_level.priority = query_row[3]
access_level.display_order = query_row[4]
access_level.active = query_row[5]
return access_level
def __repr__(self):
return f'''
id: {self.id_access_level[0] if isinstance(self.id_access_level, tuple) else self.id_access_level}
code: {self.code[0] if isinstance(self.code, tuple) else self.code}
name: {self.name[0] if isinstance(self.name, tuple) else self.name}
description: {self.description[0] if isinstance(self.description, tuple) else self.description}
priority: {self.priority[0] if isinstance(self.priority, tuple) else self.priority}
display_order: {self.display_order}
active: {self.active}
'''
def to_json(self):
return {
self.ATTR_ID_ACCESS_LEVEL: self.id_access_level[0] if isinstance(self.id_access_level, tuple) else self.id_access_level,
self.FLAG_CODE: self.code[0] if isinstance(self.code, tuple) else self.code,
self.FLAG_NAME: self.name[0] if isinstance(self.name, tuple) else self.name,
self.FLAG_DESCRIPTION: self.description[0] if isinstance(self.description, tuple) else self.description,
self.FLAG_PRIORITY: self.priority[0] if isinstance(self.priority, tuple) else self.priority,
self.FLAG_DISPLAY_ORDER: self.display_order,
self.FLAG_ACTIVE: self.active
}
def to_json_option(self):
return {
'value': self.id_access_level,
'text': self.name
}
@classmethod
def from_json(cls, json):
print(f'Access Level.from_json: {json}')
access_level = cls()
access_level.id_access_level = json[cls.ATTR_ID_ACCESS_LEVEL],
access_level.code = json[cls.FLAG_CODE],
access_level.name = json[cls.FLAG_NAME],
access_level.priority = json[cls.FLAG_PRIORITY],
access_level.description = json[cls.FLAG_DESCRIPTION],
access_level.display_order = json[cls.FLAG_DISPLAY_ORDER]
access_level.active = json[cls.FLAG_ACTIVE]
return access_level
class Filters_Access_Level(BaseModel):
get_inactive_access_level: bool
def __init__(self, get_inactive_access_level = False):
super().__init__(get_inactive_access_level = get_inactive_access_level)
def to_json(self):
return {
'a_get_inactive_access_level': self.get_inactive_access_level
}
@classmethod
def from_json(cls, json):
filters = cls()
filters.get_inactive_access_level = json['a_get_inactive_access_level']
return filters

View File

@@ -61,8 +61,8 @@ class Basket_Item():
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')
def add_product_price_discount(self, discount):
av.val_instance(discount, 'discount', 'Basket_Item.add_product_price_discount', Discount, v_arg_type='class attribute')
self.discounts.append(discount)
def set_delivery_option(self, delivery_option):

View File

@@ -66,8 +66,8 @@ class Currency(db.Model):
currency.display_order = query_row[5]
return currency
"""
def from_DB_product(query_row):
_m = 'Currency.from_DB_product'
def from_DB_get_many_product_catalogue(query_row):
_m = 'Currency.from_DB_get_many_product_catalogue'
v_arg_type = 'class attribute'
currency = Currency()
currency.id_permutation = query_row[0]

View File

@@ -63,7 +63,7 @@ class Delivery_Option(db.Model):
display_order = db.Column(db.Integer)
def __init__(self):
self.delivery_regions = []
def from_DB_product(query_row):
def from_DB_get_many_product_catalogue(query_row):
option = Delivery_Option()
option.id_option = query_row[0]
option.id_product = query_row[1]

View File

@@ -59,7 +59,7 @@ class Delivery_Region(db.Model):
self.code = code
self.display_order = display_order
"""
def from_DB_product(query_row):
def from_DB_get_many_product_catalogue(query_row):
region = Delivery_Region()
region.id_region = query_row[0]
region.name = query_row[1]

View File

@@ -37,7 +37,7 @@ class Discount(db.Model):
def __init__(self):
self.delivery_regions = []
def from_DB_product(query_row):
def from_DB_get_many_product_catalogue(query_row):
discount = Discount()
discount.id_discount = query_row[0]
discount.id_category = query_row[1]

View File

@@ -73,8 +73,8 @@ class Image(db.Model):
self.display_order = display_order
super().__init__()
"""
def from_DB_product(query_row):
_m = 'Image.from_DB_product'
def from_DB_get_many_product_catalogue(query_row):
_m = 'Image.from_DB_get_many_product_catalogue'
# print(f'image: {query_row}')
image = Image()
image.id_image = query_row[0]

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
)

View File

@@ -12,6 +12,7 @@ Business object for product category
# internal
import lib.argument_validation as av
from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
from business_objects.store.product import Product, Product_Permutation, Product_Price
from business_objects.store.product_variation import Product_Variation
from business_objects.store.image import Image
@@ -24,36 +25,16 @@ from extensions import db
from pydantic import BaseModel
from typing import ClassVar
"""
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 Product_Category(db.Model, Store_Base):
class Product_Category(SQLAlchemy_ABC, Store_Base):
FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = 'id_access_level_required'
__tablename__ = 'Shop_Product_Category_Temp'
id_category = db.Column(db.Integer, primary_key=True)
code = db.Column(db.String(50))
name = db.Column(db.String(255))
description = db.Column(db.String(4000))
id_access_level_required = db.Column(db.Integer)
name_access_level_required = db.Column(db.String(255))
display_order = db.Column(db.Integer)
active = db.Column(db.Boolean)
can_view = db.Column(db.Boolean)
@@ -61,39 +42,25 @@ class Product_Category(db.Model, Store_Base):
can_admin = db.Column(db.Boolean)
created_on = db.Column(db.DateTime)
created_by = 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
"""
def __init__(self):
self.products = []
self.product_index = {}
super().__init__()
Store_Base.__init__(self)
def from_DB_product(query_row):
self.name_access_level_required = None
def from_DB_get_many_product_catalogue(query_row):
category = Product_Category()
category.id_category = query_row[0]
category.code = query_row[1]
category.name = query_row[2]
category.description = query_row[3]
category.id_access_level_required = query_row[4]
category.display_order = query_row[5]
category.active = query_row[6]
category.can_view = query_row[7]
category.can_edit = query_row[8]
category.can_admin = query_row[9]
category.name_access_level_required = query_row[5]
category.display_order = query_row[6]
category.active = query_row[7]
category.can_view = query_row[8]
category.can_edit = query_row[9]
category.can_admin = query_row[10]
return category
"""
def key_product_index_from_ids_product_permutation(id_product, id_permutation):
@@ -128,39 +95,39 @@ class Product_Category(db.Model, Store_Base):
except KeyError:
self.product_index[product.id_product] = len(self.products)
self.products.append(product)
def add_permutation(self, permutation):
_m = 'Category.add_permutation'
def add_product_permutation(self, permutation):
_m = 'Category.add_product_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', Product_Variation)
self.products[index_product].add_product_permutation(permutation)
def add_product_variation(self, variation):
av.val_instance(variation, 'variation', 'Category.add_product_variation', Product_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', Product_Price)
self.products[index_product].add_product_variation(variation)
def add_product_price(self, price):
av.val_instance(price, 'price', 'Category.add_product_price', Product_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)
self.products[index_product].add_product_price(price)
def add_product_image(self, image):
av.val_instance(image, 'image', 'Category.add_product_image', Image)
index_product = self.get_index_product_from_id(image.id_product)
self.products[index_product].add_image(image)
self.products[index_product].add_product_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)
def add_product_price_discount(self, discount):
av.val_instance(discount, 'discount', 'Category.add_product_price_discount', Discount)
index_product = self.get_index_product_from_id(discount.id_product)
self.products[index_product].add_discount(discount)
self.products[index_product].add_product_price_discount(discount)
def add_stock_item(self, stock_item):
av.val_instance(stock_item, 'stock_item', 'Category.add_stock_item', Stock_Item)
index_product = self.get_index_product_from_id(stock_item.id_product)
self.products[index_product].add_stock_item(stock_item)
def get_all_variation_trees(self):
def get_all_product_variation_trees(self):
for product in self.products:
if product.has_variations:
print(f'product with id:{product.id_product} has variations')
@@ -181,14 +148,17 @@ class Product_Category(db.Model, Store_Base):
code: {self.code[0] if isinstance(self.code, tuple) else self.code}
name: {self.name[0] if isinstance(self.name, tuple) else self.name}
description: {self.description[0] if isinstance(self.description, tuple) else self.description}
access_level: {self.name_access_level_required[0] if isinstance(self.name_access_level_required, tuple) else self.name_access_level_required}
display_order: {self.display_order}
active: {self.active}
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()
"""
def is_available(self):
if len(self.products) == 0:
return False
@@ -196,22 +166,25 @@ class Product_Category(db.Model, Store_Base):
if product.is_available():
return True
return False
def to_list_rows_permutation(self):
def to_permutation_row_list(self):
list_rows = []
for product in self.products:
list_rows += product.to_list_rows_permutation()
list_rows += product.to_permutation_row_list()
return list_rows
def to_list_products(self):
def to_product_option_list(self):
list_products = []
for product in self.products:
list_products.append({'value': product.id_product, 'text': product.name})
return list_products
def to_json(self):
return {
self.FLAG_KEY_PRIMARY: self.ATTR_ID_PRODUCT_CATEGORY,
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category[0] if isinstance(self.id_category, tuple) else self.id_category,
self.FLAG_CODE: self.code[0] if isinstance(self.code, tuple) else self.code,
self.FLAG_NAME: self.name[0] if isinstance(self.name, tuple) else self.name,
self.FLAG_DESCRIPTION: self.description[0] if isinstance(self.description, tuple) else self.description,
self.ATTR_ID_ACCESS_LEVEL: self.id_access_level_required[0] if isinstance(self.id_access_level_required, tuple) else self.id_access_level_required,
self.FLAG_ACCESS_LEVEL_REQUIRED: self.name_access_level_required[0] if isinstance(self.name_access_level_required, tuple) else self.name_access_level_required,
self.FLAG_DISPLAY_ORDER: self.display_order,
self.FLAG_ACTIVE: self.active,
self.FLAG_CAN_VIEW: self.can_view,
@@ -222,31 +195,42 @@ class Product_Category(db.Model, Store_Base):
def from_json(cls, json):
print(f' Category.from_json: {json}')
category = cls()
category.id_category = json.get(cls.ATTR_ID_PRODUCT_CATEGORY),
category.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY],
category.code = json[cls.FLAG_CODE],
category.name = json[cls.FLAG_NAME],
category.description = json[cls.FLAG_DESCRIPTION],
category.id_access_level_required = json[cls.ATTR_ID_ACCESS_LEVEL],
category.name_access_level_required = json.get(cls.FLAG_ACCESS_LEVEL_REQUIRED, ''),
category.display_order = json[cls.FLAG_DISPLAY_ORDER]
category.active = json[cls.FLAG_ACTIVE]
category.can_view = json.get(cls.FLAG_CAN_VIEW, False)
category.can_edit = json.get(cls.FLAG_CAN_EDIT, False)
category.can_admin = json.get(cls.FLAG_CAN_ADMIN, False)
return category
"""
def to_json_str(self):
return {
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category[0] if isinstance(self.id_category, tuple) else self.id_category,
self.FLAG_CODE: self.code[0] if isinstance(self.code, tuple) else self.code,
self.FLAG_NAME: self.name[0] if isinstance(self.name, tuple) else self.name,
self.FLAG_DESCRIPTION: self.description[0] if isinstance(self.description, tuple) else self.description,
self.ATTR_ID_ACCESS_LEVEL: self.id_access_level_required[0] if isinstance(self.id_access_level_required, tuple) else self.id_access_level_required,
self.FLAG_ACCESS_LEVEL_REQUIRED: self.name_access_level_required[0] if isinstance(self.name_access_level_required, tuple) else self.name_access_level_required,
self.FLAG_DISPLAY_ORDER: self.display_order,
self.FLAG_ACTIVE: self.output_bool(self.active),
self.FLAG_CAN_VIEW: self.output_bool(self.can_view),
self.FLAG_CAN_EDIT: self.output_bool(self.can_edit),
self.FLAG_CAN_ADMIN: self.output_bool(self.can_admin)
}
"""
@staticmethod
def output_bool(value):
return av.input_bool(value, 'Product_Category bool attribute', 'Product_Category.output_bool')
def to_json_option(self):
return {
'value': self.id_category,
'text': self.name
}
"""
class Filters_Product_Category(BaseModel, Store_Base):
ids_product_category: str
@@ -284,42 +268,45 @@ class Filters_Product_Category(BaseModel, Store_Base):
filters = cls()
filters.ids_product_category = json['a_ids_product_category'],
filters.ids_product = json['a_ids_product']
"""
class Filters_Product_Category(BaseModel, Store_Base):
is_not_empty_only: bool
active_only: bool
def __init__(self, is_not_empty_only, active_only):
super().__init__(is_not_empty_only=is_not_empty_only, active_only=active_only)
class Filters_Product_Category(Get_Many_Parameters_Base):
FLAG_IS_NOT_EMPTY: ClassVar[str] = 'is_not_empty'
is_not_empty: bool
active: bool
def __init__(self, is_not_empty, active):
super().__init__(is_not_empty=is_not_empty, active=active)
@classmethod
def get_default(cls):
return cls(
is_not_empty_only = False,
active_only = True
is_not_empty = False,
active = True
)
def to_json(self):
return {
'is_not_empty_only': self.is_not_empty_only,
'active_only': self.active_only
self.FLAG_IS_NOT_EMPTY: self.is_not_empty,
self.FLAG_ACTIVE: self.active
}
@classmethod
def from_json(cls, json):
return cls(
is_not_empty_only = json['is_not_empty_only'],
active_only = json['active_only']
is_not_empty = json['is_not_empty'],
active = json['active']
)
@classmethod
def from_form(cls, form):
return cls(
is_not_empty_only = av.input_bool(form.is_not_empty.data, 'is_not_empty', 'Filters_Product_Category.from_form'),
active_only = av.input_bool(form.active.data, 'active', 'Filters_Product_Category.from_form')
is_not_empty = av.input_bool(form.is_not_empty.data, 'is_not_empty', 'Filters_Product_Category.from_form'),
active = av.input_bool(form.active.data, 'active', 'Filters_Product_Category.from_form')
)
"""
class Container_Product_Category(Store_Base):
class Product_Category_Container(Store_Base):
categories: list
def __init__(self):
self.categories = []
def add_category(self, category):
av.val_instance(category, 'category', 'Container_Product_Categories.add_category', Product_Category)
def add_product_category(self, category):
av.val_instance(category, 'category', 'Container_Product_Categories.add_product_category', Product_Category)
self.categories.append(category)
def get_index_category_from_id(self, id_category):
for index_category in range(len(self.categories)):
@@ -340,73 +327,89 @@ class Container_Product_Category(Store_Base):
av.val_instance(product, 'product', 'Container_Product_Categories.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', 'Container_Product_Categories.add_permutation', Product_Permutation)
def add_product_permutation(self, permutation):
av.val_instance(permutation, 'permutation', 'Container_Product_Categories.add_product_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', 'Container_Product_Categories.add_variation', Product_Variation)
self.categories[index_category].add_product_permutation(permutation)
def add_product_variation(self, variation):
av.val_instance(variation, 'variation', 'Container_Product_Categories.add_product_variation', Product_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', 'Container_Product_Categories.add_price', Product_Price)
self.categories[index_category].add_product_variation(variation)
def add_product_price(self, price):
av.val_instance(price, 'price', 'Container_Product_Categories.add_product_price', Product_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', 'Container_Product_Categories.add_image', Image)
self.categories[index_category].add_product_price(price)
def add_product_image(self, image):
av.val_instance(image, 'image', 'Container_Product_Categories.add_product_image', Image)
index_category = self.get_index_category_from_id(image.id_category)
self.categories[index_category].add_image(image)
self.categories[index_category].add_product_image(image)
def add_delivery_option(self, delivery_option):
av.val_instance(delivery_option, 'delivery_option', 'Container_Product_Categories.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', 'Container_Product_Categories.add_discount', Discount)
def add_product_price_discount(self, discount):
av.val_instance(discount, 'discount', 'Container_Product_Categories.add_product_price_discount', Discount)
index_category = self.get_index_category_from_id(discount.id_category)
self.categories[index_category].add_discount(discount)
self.categories[index_category].add_product_price_discount(discount)
def add_stock_item(self, stock_item):
av.val_instance(stock_item, 'stock_item', 'Container_Product_Categories.add_stock_item', Stock_Item)
index_category = self.get_index_category_from_id(stock_item.id_category)
self.categories[index_category].add_stock_item(stock_item)
def get_all_variation_trees(self):
def get_all_product_variation_trees(self):
for category in self.categories:
category.get_all_variation_trees()
category.get_all_product_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):
"""
def get_category_count(self):
return len(self.categories)
def to_list_rows_permutation(self):
def to_permutation_row_list(self):
list_rows = []
for category in self.categories:
list_rows += category.to_list_rows_permutation()
list_rows += category.to_permutation_row_list()
return list_rows
def to_list_category_options(self):
def to_category_option_list(self):
list_categories = []
for category in self.categories:
list_categories.append({'value': category.id_category, 'text': category.name})
return list_categories
def to_list_products(self):
def to_product_option_list(self):
list_products = []
for category in self.categories:
# list_products.append(category.to_list_products())
# list_products.append(category.to_product_option_list())
for product in category.products:
list_products.append({'value': product.id_product, 'text': product.name, Product.ATTR_ID_PRODUCT_CATEGORY: product.id_category})
return list_products
def to_dict_lists_products(self):
def get_product_option_lists_by_category(self):
dict_lists_products = {}
for category in self.categories:
dict_lists_products[category.id_category] = category.to_list_products()
dict_lists_products[category.id_category] = category.to_product_option_list()
return dict_lists_products
def to_json(self):
return {
'categories': [category.to_json() for category in self.categories]
f'{self.FLAG_ROWS}': [category.to_json() for category in self.categories]
}
"""
def to_json_str(self):
return {
'categories': [category.to_json_str() for category in self.categories]
}
f'{self.FLAG_ROWS}': [category.to_json_str() for category in self.categories]
}
"""
@classmethod
def from_json(cls, json):
return None
def to_json_option(self):
return None
def to_temporary_record(self):
excluded_attributes = {
column.name: getattr(self, column.name)
for column in self.__table__.columns
if column.name not in ['created_on', 'created_by']
}
return self.to_object_with_missing_attributes(excluded_attributes)

View File

@@ -21,6 +21,7 @@ from business_objects.store.product_price import Product_Price
from business_objects.store.stock_item import Stock_Item
from business_objects.store.store_base import Store_Base
from business_objects.store.product_variation import Product_Variation
from business_objects.store.product_variation_tree import Product_Variation_Tree
from extensions import db
# external
from datetime import datetime, timedelta
@@ -64,6 +65,7 @@ class Product_Permutation(db.Model, Store_Base):
# form_basket_edit: Form_Basket_Edit
# is_unavailable_in_currency_or_region: bool
# is_available: bool
# variation_tree
def __init__(self):
self.variations = []
@@ -84,9 +86,10 @@ class Product_Permutation(db.Model, Store_Base):
self.form_basket_edit = Form_Basket_Edit()
self.is_unavailable_in_currency_or_region = False
# self.is_available = False
self.variation_tree = None
def from_DB_product(query_row):
_m = 'Product_Permutation.from_DB_product'
def from_DB_get_many_product_catalogue(query_row):
_m = 'Product_Permutation.from_DB_get_many_product_catalogue'
v_arg_type = 'class attribute'
print(f'query_row: {query_row}')
permutation = Product_Permutation()
@@ -155,7 +158,7 @@ class Product_Permutation(db.Model, Store_Base):
if permutation.has_variations:
for jsonProductVariation in json[cls.ATTR_ID_PRODUCT_VARIATION]:
variation = Product_Variation.from_json(jsonProductVariation)
permutation.add_variation(variation)
permutation.add_product_variation(variation)
permutation.quantity_stock = json[cls.FLAG_QUANTITY_STOCK]
permutation.quantity_min = json[cls.FLAG_QUANTITY_MIN]
permutation.quantity_max = json[cls.FLAG_QUANTITY_MAX]
@@ -185,6 +188,13 @@ class Product_Permutation(db.Model, Store_Base):
'delivery_options': {self.delivery_options},
'prices': {self.prices}
}
def to_json_option(self):
return {
'value': self.id_permutation,
'text': self.get_name_variations()
}
def get_name_variations(self):
return self.variation_tree.get_name_variations()
def is_available(self):
return len(self.prices) > 0
def get_price(self):
@@ -270,8 +280,9 @@ class Product_Permutation(db.Model, Store_Base):
price_GBP_min: {self.price_GBP_min}
"""
def add_variation(self, variation):
_m = 'Product_Permutation.add_variation'
def add_product_variation(self, variation):
_m = 'Product_Permutation.add_product_variation'
"""
av.val_instance(variation, 'variation', _m, Product_Variation)
try:
self.variation_index[variation.id_variation]
@@ -279,8 +290,13 @@ class Product_Permutation(db.Model, Store_Base):
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'
"""
if self.variation_tree is None:
self.variation_tree = Product_Variation_Tree.from_product_variation(variation)
else:
self.variation_tree.add_product_variation(variation)
def add_product_price(self, price):
_m = 'Product_Permutation.add_product_price'
av.val_instance(price, 'price', _m, Product_Price)
try:
self.price_index[price.display_order]
@@ -288,8 +304,8 @@ class Product_Permutation(db.Model, Store_Base):
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'
def add_product_image(self, image):
_m = 'Product_Permutation.add_product_image'
av.val_instance(image, 'image', _m, Image)
try:
self.image_index[image.id_image]
@@ -306,8 +322,8 @@ class Product_Permutation(db.Model, Store_Base):
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'
def add_product_price_discount(self, discount):
_m = 'Product_Permutation.add_product_price_discount'
av.val_instance(discount, 'discount', _m, Discount)
try:
self.discount_index[discount.display_order]
@@ -352,8 +368,8 @@ class Permutation_Product_Variation_Link(db.Model):
id_category = db.Column(db.Integer)
id_variation = db.Column(db.Integer)
def from_DB_product(query_row):
_m = 'Permutation_Product_Variation_Link.from_DB_product'
def from_DB_get_many_product_catalogue(query_row):
_m = 'Permutation_Product_Variation_Link.from_DB_get_many_product_catalogue'
v_arg_type = 'class attribute'
link = Permutation_Product_Variation_Link()
link.id_permutation = query_row[0]

View File

@@ -42,8 +42,8 @@ class Product_Price(db.Model, Store_Base):
super().__init__()
Store_Base.__init__(self)
def from_DB_product(query_row):
# _m = 'Product_Price.from_DB_product'
def from_DB_get_many_product_catalogue(query_row):
# _m = 'Product_Price.from_DB_get_many_product_catalogue'
price = Product_Price()
price.id_price = query_row[0]
price.id_permutation = query_row[1]
@@ -90,6 +90,11 @@ class Product_Price(db.Model, Store_Base):
self.FLAG_VALUE_LOCAL_VAT_EXCL: {self.value_local_VAT_excl},
self.FLAG_DISPLAY_ORDER: {self.display_order}
}
def to_json_option(self):
return {
'value': self.id_price,
'text': f'{self.symbol_currency} {self.value_local_VAT_incl}'
}
@classmethod
def from_json(cls, json):

View File

@@ -56,7 +56,7 @@ class Product_Variation(db.Model, Store_Base):
super().__init__()
Store_Base.__init__(self)
def from_DB_product(query_row):
def from_DB_get_many_product_catalogue(query_row):
variation = Product_Variation.from_DB_variation(query_row)
variation.id_product = query_row[11]
variation.id_permutation = query_row[12]
@@ -122,6 +122,11 @@ class Product_Variation(db.Model, Store_Base):
self.KEY_ACTIVE_VARIATION_TYPE: self.active_variation_type,
self.KEY_ACTIVE_VARIATION: self.active_variation,
}
def to_json_option(self):
return {
'value': self.id_variation,
'text': self.name_variation
}
def to_json_variation_type(self):
return {
@@ -159,7 +164,7 @@ class Product_Variation_Filters():
@staticmethod
def from_form(form):
av.val_instance(form, 'form', 'User_Filters.from_form', Form_Filters_Product_Variation)
get_inactive = av.input_bool(form.active_only.data, "active_only", "User_Filters.from_form")
get_inactive = av.input_bool(form.active.data, "active", "User_Filters.from_form")
id_user = form.id_user.data
return User_Filters(
get_all_user = (id_user is None),
@@ -197,8 +202,8 @@ class Product_Variation_Filters():
class Product_Variation_List(BaseModel):
variations: list = []
def add_variation(self, variation):
av.val_instance(variation, 'variation', 'Product_Variation_List.add_variation', Product_Variation)
def add_product_variation(self, variation):
av.val_instance(variation, 'variation', 'Product_Variation_List.add_product_variation', Product_Variation)
self.variations.append(variation)
def __repr__(self):

View File

@@ -38,24 +38,19 @@ class Product_Variation_Tree_Node():
class Product_Variation_Tree():
node_root: Product_Variation_Tree_Node
def from_node_root(node_root):
tree = Product_Variation_Tree()
@classmethod
def from_node_root(cls, node_root):
tree = cls()
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
@classmethod
def from_variation_root(cls, variation_root):
node_root = Product_Variation_Tree_Node.from_variation_and_node_parent(variation_root, None)
return cls.from_node_root(node_root)
def is_equal(self, tree):
my_type_list = self.get_variation_type_list()
my_type_list = self.get_product_variations()
sz_me = len(my_type_list)
other_type_list = tree.get_variation_type_list()
other_type_list = tree.get_product_variations()
sz_other = len(other_type_list)
is_equal = (sz_me == sz_other)
if is_equal:
@@ -71,3 +66,44 @@ class Product_Variation_Tree():
for depth in range(depth_max - 1):
node = Product_Variation_Tree_Node.from_variation_and_node_parent(product_permutation.variations[depth + 1], node)
return Product_Variation_Tree.from_node_root(node_root)
def from_product_variation(product_variation):
node_root = Product_Variation_Tree_Node.from_variation_and_node_parent(product_variation, None)
return Product_Variation_Tree.from_node_root(node_root)
def get_name_variations(self):
node = self.node_root
name = node.variation.name_variation_type
at_leaf_node = node.is_leaf()
while not at_leaf_node:
node = node.nodes_child[0]
name += f', {node.variation.name_variation_type}'
at_leaf_node = node.is_leaf()
return name
def get_node_leaf(self):
node = self.node_root
at_leaf_node = node.is_leaf()
while not at_leaf_node:
node = node.nodes_child[0]
at_leaf_node = node.is_leaf()
return node
def add_product_variation(self, variation):
node_leaf = self.get_node_leaf()
node_new = Product_Variation_Tree_Node.from_variation_and_node_parent(variation, node_leaf)
node_leaf.add_child(node_new)
def get_product_variation_types(self):
types = []
node = self.node_root
at_leaf_node = node.is_leaf()
while not at_leaf_node:
types.append(node.variation.name_variation_type)
node = node.nodes_child[0]
at_leaf_node = node.is_leaf()
return types
def get_product_variations(self):
variations = []
node = self.node_root
at_leaf_node = node.is_leaf()
while not at_leaf_node:
variations.append(node.variation)
node = node.nodes_child[0]
at_leaf_node = node.is_leaf()
return variations

View File

@@ -173,6 +173,19 @@ class Stock_Item(db.Model, Store_Base):
permutations: {self.permutations}
variation trees: {self.variation_trees}
'''
def to_json(self):
return {
self.ATTR_ID_PRODUCT: {self.id_product},
self.ATTR_ID_PRODUCT_CATEGORY: {self.id_category},
self.FLAG_NAME: {self.name},
self.FLAG_DISPLAY_ORDER: {self.display_order},
self.FLAG_CAN_VIEW: {self.can_view},
self.FLAG_CAN_EDIT: {self.can_edit},
self.FLAG_CAN_ADMIN: {self.can_admin},
self.FLAG_HAS_VARIATIONS: {self.has_variations},
self.FLAG_PERMUTATIONS: {self.permutations},
self.FLAG_VARIATION_TREES: {self.variation_trees},
}
def has_permutations(self):
return len(self.permutations) > 0
def is_available(self):
@@ -183,12 +196,17 @@ class Stock_Item(db.Model, Store_Base):
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())
return list_rows
"""
def to_json_option(self):
return {
'value': self.id_stock_item,
'text': self.id_stock_item
}
@dataclass
class Stock_Item_Filters():

View File

@@ -11,10 +11,52 @@ Abstract business object for store objects
"""
# internal
# from helpers.DEPRECATED.helper_abc import Interface_ABC
from extensions import db
import lib.argument_validation as av
# external
from typing import ClassVar
"""
class I_Store_Base():
@abstractmethod
def __repr__(self):
pass
@classmethod
@abstractmethod
def from_json(cls, json):
pass
@abstractmethod
def to_json(self):
pass
@abstractmethod
def to_json_option(self):
pass
@abstractmethod
def test_69 (self):
pass
""
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
for name, value in vars(Store_Base).items():
if getattr(value, "__isabstractmethod__", False):
if name not in cls.__dict__:
raise TypeError(f"Can't instantiate class {cls.__name__} "
f"without implementation of abstract method {name}")
subclass_value = cls.__dict__[name]
if (isinstance(value, (staticmethod, classmethod)) and
not isinstance(subclass_value, type(value))):
raise TypeError(f"Abstract {type(value).__name__} {name} in {cls.__name__} "
f"must be implemented as a {type(value).__name__}")
def __new__(cls, *args, **kwargs):
if cls is Store_Base:
raise TypeError("Can't instantiate abstract class Store_Base directly")
return super().__new__(cls)
""
"""
class Store_Base():
ATTR_ID_ACCESS_LEVEL: ClassVar[str] = 'id_access_level'
ATTR_ID_CURRENCY: ClassVar[str] = 'id_currency'
# ATTR_ID_CURRENCY_COST: ClassVar[str] = 'id_currency_cost'
ATTR_ID_DELIVERY_REGION: ClassVar[str] = 'id_delivery_region'
@@ -28,6 +70,7 @@ class Store_Base():
ATTR_ID_PRODUCT_VARIATION: ClassVar[str] = 'id_variation'
ATTR_ID_PRODUCT_VARIATION_TYPE: ClassVar[str] = 'id_variation_type'
ATTR_ID_STOCK_ITEM: ClassVar[str] = 'id_stock_item'
FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = 'access_level_required'
FLAG_ACTIVE: ClassVar[str] = 'active'
FLAG_CAN_ADMIN: ClassVar[str] = 'can_admin'
FLAG_CAN_EDIT: ClassVar[str] = 'can_edit'
@@ -35,31 +78,17 @@ class Store_Base():
FLAG_CODE: ClassVar[str] = 'code'
FLAG_DESCRIPTION: ClassVar[str] = 'description'
FLAG_DISPLAY_ORDER: ClassVar[str] = 'display_order'
FLAG_HAS_VARIATIONS: ClassVar[str] = 'has_variations'
FLAG_IS_NOT_EMPTY: ClassVar[str] = 'is_not_empty'
FLAG_KEY_PRIMARY: ClassVar[str] = 'key_primary'
FLAG_NAME: ClassVar[str] = 'name'
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
for name, value in vars(Store_Base).items():
if getattr(value, "__isabstractmethod__", False):
if name not in cls.__dict__:
raise TypeError(f"Can't instantiate class {cls.__name__} "
f"without implementation of abstract method {name}")
subclass_value = cls.__dict__[name]
if (isinstance(value, (staticmethod, classmethod)) and
not isinstance(subclass_value, type(value))):
raise TypeError(f"Abstract {type(value).__name__} {name} in {cls.__name__} "
f"must be implemented as a {type(value).__name__}")
def __new__(cls, *args, **kwargs):
if cls is Store_Base:
raise TypeError("Can't instantiate abstract class Store_Base directly")
return super().__new__(cls)
def __repr__(self):
pass
FLAG_PERMUTATIONS: ClassVar[str] = 'permutations'
FLAG_PRIORITY: ClassVar[str] = 'priority'
FLAG_ROWS: ClassVar[str] = 'rows'
FLAG_VARIATION_TREES: ClassVar[str] = 'variation_trees'
@classmethod
def from_json(cls, json):
pass
def to_json(self):
pass
def output_bool(cls, value):
return av.input_bool(value, f'{cls.__name__} bool attribute', f'{cls.__name__}.output_bool')
@staticmethod
def convert_list_objects_to_list_options(objects):
return [object.to_json_option() for object in objects]

View File

@@ -153,7 +153,7 @@ class Stripe_Product(db.Model):
delivery_options: {self.delivery_options}
'''
def add_discount(self, discount):
def add_product_price_discount(self, discount):
_m = 'Category.add_product'
av.val_instance(discount, 'discount', _m, Discount)
# self.product_index.append(len(self.products))

View File

@@ -160,7 +160,7 @@ class User_Filters():
@staticmethod
def from_form(form):
av.val_instance(form, 'form', 'User_Filters.from_form', Form_Filters_User)
get_inactive = av.input_bool(form.active_only.data, "active_only", "User_Filters.from_form")
get_inactive = av.input_bool(form.active.data, "active", "User_Filters.from_form")
id_user = form.id_user.data
return User_Filters(
get_all_user = (id_user is None),
@@ -212,7 +212,7 @@ class User_Filters():
@staticmethod
def from_form(form):
av.val_instance(form, 'form', 'User_Filters.from_form', Form_Filters_User)
get_inactive = av.input_bool(form.active_only.data, "active_only", "User_Filters.from_form")
get_inactive = av.input_bool(form.active.data, "active", "User_Filters.from_form")
return User_Filters(
ids_user = form.id_user.data,
get_inactive_users = get_inactive,