""" 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_Filters_Permutation 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 from business_objects.stock_item import Stock_Item # external from enum import Enum from datetime import datetime, timedelta import locale from flask_sqlalchemy import SQLAlchemy from dataclasses import dataclass from typing import ClassVar # 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): ATTR_ID_CATEGORY: ClassVar[str] = Variation.ATTR_ID_CATEGORY # 'id-category' ATTR_ID_PRODUCT: ClassVar[str] = Variation.ATTR_ID_PRODUCT # 'id-product' ATTR_ID_PERMUTATION: ClassVar[str] = Variation.ATTR_ID_PERMUTATION # 'id-permutation' FLAG_VARIATIONS: ClassVar[str] = 'variations' 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[22] product.can_view = av.input_bool(query_row[24], "can_view", _m, v_arg_type=v_arg_type) product.can_edit = av.input_bool(query_row[25], "can_edit", _m, v_arg_type=v_arg_type) product.can_admin = av.input_bool(query_row[26], "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) 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] self.permutations[index_permutation].add_stock_item(stock_item) def has_permutations(self): return len(self.permutations) > 0 def is_available(self): if len(self.permutations) == 0: return False for permutation in self.permutations: if permutation.is_available(): return True return False def to_list_rows_permutation(self): list_rows = [] for permutation in self.permutations: list_rows.append(permutation.to_row_permutation()) return list_rows class Product_Permutation(db.Model): FLAG_QUANTITY_STOCK = 'quantity-stock' FLAG_QUANTITY_MIN = 'quantity-min' FLAG_QUANTITY_MAX = 'quantity-max' FLAG_COST_LOCAL = 'cost-local' 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) id_currency_cost = db.Column(db.Integer) code_currency_cost = db.Column(db.String(3)) symbol_currency_cost = db.Column(db.String(3)) cost_local = 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 = {} self.stock_items = [] self.stock_item_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 = False 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.id_currency_cost = query_row[7] permutation.code_currency_cost = query_row[8] permutation.symbol_currency_cost = query_row[9] permutation.cost_local = query_row[6] permutation.has_variations = query_row[4] permutation.id_category = query_row[5] permutation.latency_manufacture = query_row[11] permutation.quantity_min = query_row[12] permutation.quantity_max = query_row[13] permutation.quantity_step = query_row[14] permutation.quantity_stock = query_row[15] permutation.id_stripe_product = query_row[16] permutation.is_subscription = av.input_bool(query_row[17], "is_subscription", _m, v_arg_type=v_arg_type) permutation.name_recurrence_interval = query_row[18] permutation.name_plural_recurrence_interval = query_row[19] permutation.count_recurrence_interval = query_row[20] permutation.display_order = query_row[23] permutation.can_view = av.input_bool(query_row[24], "can_view", _m, v_arg_type=v_arg_type) permutation.can_edit = av.input_bool(query_row[25], "can_edit", _m, v_arg_type=v_arg_type) permutation.can_admin = av.input_bool(query_row[26], "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 from_json(jsonPermutation): permutation = Product_Permutation() permutation.id_category = jsonPermutation[Product.ATTR_ID_CATEGORY] permutation.id_product = jsonPermutation[Product.ATTR_ID_PRODUCT] permutation.id_permutation = jsonPermutation[Product.ATTR_ID_PERMUTATION] permutation.has_variations = len(jsonPermutation[Product.FLAG_VARIATIONS]) > 0 if permutation.has_variations: for jsonVariation in jsonPermutation[Product.FLAG_VARIATIONS]: variation = Variation.from_json(jsonVariation) permutation.add_variation(variation) permutation.quantity_stock = jsonPermutation[Product_Permutation.FLAG_QUANTITY_STOCK] permutation.quantity_min = jsonPermutation[Product_Permutation.FLAG_QUANTITY_MIN] permutation.quantity_max = jsonPermutation[Product_Permutation.FLAG_QUANTITY_MAX] return permutation def is_available(self): return len(self.prices) > 0 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 """ return self.code_currency_cost if self.symbol_currency_cost == '' else self.symbol_currency_cost def output_variations(self): if not self.has_variations: return '' return '\n'.join([f'{variation.name_variation_type}: {variation.name_variation}' for variation in self.variations]) def output_variations_jsonify(self): if not self.has_variations: return '' return ','.join([f'{variation.name_variation_type}: {variation.name_variation}' for variation in self.variations]) """ 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 add_stock_item(self, stock_item): av.val_instance(stock_item, 'stock_item', 'Product_Permutation.add_stock_item', Stock_Item) self.stock_items.append(stock_item) 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 def to_row_permutation(self): a = { Product.ATTR_ID_CATEGORY: self.id_category, Product.ATTR_ID_PRODUCT: self.id_product, Product.FLAG_VARIATIONS: self.output_variations(), Product_Permutation.FLAG_QUANTITY_STOCK: self.quantity_stock, Product_Permutation.FLAG_QUANTITY_MIN: self.quantity_min, Product_Permutation.FLAG_QUANTITY_MAX: self.quantity_max, Product_Permutation.FLAG_COST_LOCAL: f"{self.symbol_currency_cost}{self.cost_local}" } print('permutation row: ', a) return a """ 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 get_inactive_category: bool get_first_category_only: bool ids_category: str get_all_product: bool get_inactive_product: bool get_first_product_only: bool ids_product: str get_all_permutation: bool get_inactive_permutation: bool get_first_permutation_only: bool ids_permutation: str get_all_image: bool get_inactive_image: bool get_first_image_only: bool ids_image: str get_all_region: bool get_inactive_region: bool get_first_region_only: bool ids_region: str get_all_currency: bool get_inactive_currency: bool get_first_currency_only: bool ids_currency: str get_all_discount: bool get_inactive_discount: bool ids_discount: str get_products_quantity_stock_below_min: bool def to_json(self): return { 'a_id_user': None, 'a_get_all_category': self.get_all_category, 'a_get_inactive_category': self.get_inactive_category, 'a_get_first_category_only': self.get_first_category_only, 'a_ids_category': self.ids_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(form): # if not (form is Form_Filters_Permutation): raise ValueError(f'Invalid form type: {type(form)}') av.val_instance(form, 'form', 'Product_Filters.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", "Product_Filters.from_form") print(f'form question: {type(form.is_out_of_stock)}\nbool interpretted: {get_permutations_stock_below_min}\type form: {type(form)}') return Product_Filters( get_all_category = not has_category_filter, get_inactive_category = False, get_first_category_only = False, ids_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 Product_Filters( get_all_category = True, get_inactive_category = False, get_first_category_only = False, ids_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, get_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 )