New website focusing on ERP services.
This commit is contained in:
@@ -12,7 +12,7 @@ Business object for product
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from business_objects.base import Base
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
@@ -20,9 +20,9 @@ from pydantic import BaseModel
|
||||
from typing import ClassVar
|
||||
|
||||
|
||||
class Access_Level(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_ACCESS_LEVEL
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
|
||||
class Access_Level(db.Model, Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_ACCESS_LEVEL
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME
|
||||
__tablename__ = 'Shop_Access_Level_Temp'
|
||||
id_access_level = db.Column(db.Integer, primary_key=True)
|
||||
code = db.Column(db.String(50))
|
||||
@@ -35,7 +35,7 @@ class Access_Level(db.Model, Store_Base):
|
||||
created_by = db.Column(db.Integer)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
Base.__init__(self)
|
||||
@classmethod
|
||||
def from_DB_access_level(cls, query_row):
|
||||
access_level = cls()
|
||||
@@ -83,4 +83,4 @@ class Access_Level(db.Model, Store_Base):
|
||||
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
|
||||
return access_level
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,184 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Basket Business Object
|
||||
|
||||
Description:
|
||||
Business object for basket
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
# from lib import data_types
|
||||
from business_objects.store.product import Product #, Parameters_Product
|
||||
from business_objects.store.discount import Discount
|
||||
from business_objects.store.delivery_option import Delivery_Option
|
||||
from business_objects.store.store_base import Store_Base
|
||||
# from forms import Form_Product
|
||||
# from models.model_view_store import Model_View_Store # circular
|
||||
# from datastores.datastore_store import DataStore_Store # circular
|
||||
# from forms import Form_Basket_Add, Form_Basket_Edit # possibly circular
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
# from enum import Enum
|
||||
from flask import jsonify
|
||||
import locale
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
|
||||
# CLASSES
|
||||
class Basket_Item():
|
||||
product: Product
|
||||
quantity: int
|
||||
delivery_option: Delivery_Option
|
||||
discounts: list
|
||||
# form: Form_Product
|
||||
is_included_VAT: bool
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
self.is_unavailable_in_currency_or_region = False
|
||||
self.is_available = True
|
||||
"""
|
||||
|
||||
def from_product_and_quantity_and_VAT_included(product, quantity, is_included_VAT):
|
||||
# Initialiser - validation
|
||||
_m = 'Basket_Item.from_product_and_quantity'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_instance(product, 'product', _m, Product, v_arg_type=v_arg_type)
|
||||
av.full_val_float(quantity, 'quantity', _m, product.get_quantity_min(), v_arg_type=v_arg_type)
|
||||
basket_item = Basket_Item()
|
||||
basket_item.product = product
|
||||
basket_item.quantity = quantity
|
||||
basket_item.is_included_VAT = is_included_VAT
|
||||
return basket_item
|
||||
|
||||
def add_product_price_discount(self, discount):
|
||||
av.val_instance(discount, 'discount', 'Basket_Item.add_product_price_discount', Discount, v_arg_type='class attribute')
|
||||
self.discounts.append(discount)
|
||||
|
||||
def set_delivery_option(self, delivery_option):
|
||||
av.val_instance(delivery_option, 'delivery_option', 'Basket_Item.set_delivery_option', Delivery_Option, v_arg_type='class attribute')
|
||||
self.delivery_option = delivery_option
|
||||
|
||||
def update_quantity(self, quantity):
|
||||
_m = 'Basket_Item.update_quantity'
|
||||
v_arg_type = 'class attribute'
|
||||
av.full_val_float(quantity, 'quantity', _m, self.product.get_quantity_min(), v_arg_type=v_arg_type)
|
||||
self.quantity = quantity
|
||||
|
||||
def jsonify(self):
|
||||
return jsonify(self)
|
||||
|
||||
def to_json(self):
|
||||
permutation = self.product.get_permutation_selected()
|
||||
return {
|
||||
'product_id': self.product.id_product,
|
||||
'permutation_id': permutation.id_permutation,
|
||||
'price': permutation.output_price(self.is_included_VAT),
|
||||
'quantity': self.quantity
|
||||
}
|
||||
|
||||
def get_subtotal(self):
|
||||
permutation = self.product.get_permutation_selected()
|
||||
return round(self.product.get_price_local(self.is_included_VAT) * self.quantity, 2) if permutation.is_available else 0
|
||||
|
||||
def output_currency(self):
|
||||
return self.product.output_currency()
|
||||
|
||||
def output_subtotal(self):
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
subtotal = self.get_subtotal()
|
||||
permutation = self.product.get_permutation_selected()
|
||||
return 'Not available in this currency or region' if permutation.is_unavailable_in_currency_or_region else 'Not available' if not permutation.is_available else f'{self.product.output_currency()} {locale.format_string("%d", subtotal, grouping=True)}'
|
||||
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
product: {self.product}
|
||||
quantity: {self.quantity}
|
||||
subtotal: {self.get_subtotal()}
|
||||
'''
|
||||
|
||||
class Basket(Store_Base):
|
||||
KEY_BASKET: str = 'basket'
|
||||
KEY_ID_CURRENCY: str = 'id_currency'
|
||||
KEY_ID_REGION_DELIVERY: str = 'id_region_delivery'
|
||||
KEY_IS_INCLUDED_VAT: str = 'is_included_VAT'
|
||||
KEY_ITEMS: str = 'items'
|
||||
items: list
|
||||
is_included_VAT: bool
|
||||
id_region_delivery: int
|
||||
id_currency: int
|
||||
|
||||
def __init__(self, is_included_VAT, id_currency, id_region_delivery):
|
||||
self.items = []
|
||||
self.is_included_VAT = is_included_VAT
|
||||
self.id_currency = id_currency
|
||||
self.id_region_delivery = id_region_delivery
|
||||
def add_item(self, item):
|
||||
av.val_instance(item, 'item', 'Basket.add_item', Basket_Item)
|
||||
self.items.append(item)
|
||||
def to_csv(self):
|
||||
ids_permutation = ''
|
||||
quantities_permutation = ''
|
||||
for b_i in range(len(self.items)):
|
||||
basket_item = self.items[b_i]
|
||||
product = basket_item.product
|
||||
if b_i > 0:
|
||||
ids_permutation += ','
|
||||
quantities_permutation += ','
|
||||
ids_permutation += str(product.get_id_permutation())
|
||||
quantities_permutation += str(basket_item.quantity)
|
||||
Helper_App.console_log(f'ids_permutation_basket = {ids_permutation}')
|
||||
Helper_App.console_log(f'quantities_permutation_basket = {quantities_permutation}')
|
||||
return ids_permutation, quantities_permutation
|
||||
def to_json_list(self):
|
||||
json_list = []
|
||||
for item in self.items:
|
||||
json_list.append(item.to_json())
|
||||
return json_list
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
Basket.KEY_ITEMS: self.to_json_list(),
|
||||
Basket.KEY_IS_INCLUDED_VAT: self.is_included_VAT,
|
||||
Basket.KEY_ID_CURRENCY: self.id_currency,
|
||||
Basket.KEY_ID_REGION_DELIVERY: self.id_region_delivery
|
||||
}
|
||||
def output_total(self):
|
||||
sum = 0
|
||||
for b_i in self.items:
|
||||
sum += b_i.get_subtotal()
|
||||
symbol = self.items[0].output_currency() if len(self.items) > 0 else ''
|
||||
|
||||
return f'{symbol} {locale.format_string("%d", sum, grouping=True)}'
|
||||
def len(self):
|
||||
return len(self.items)
|
||||
"""
|
||||
def get_key_product_index_from_ids_product_permutation(id_product, id_permutation):
|
||||
return f'{id_product},{"" if id_permutation is None else id_permutation}'
|
||||
"""
|
||||
def __repr__(self):
|
||||
repr = f'Basket:'
|
||||
for basket_item in self.items:
|
||||
Helper_App.console_log(f'{basket_item}')
|
||||
repr = f'{repr}\n{basket_item}'
|
||||
return repr
|
||||
|
||||
def get_ids_permutation_unavailable(self):
|
||||
ids_permutation = []
|
||||
for item in self.items:
|
||||
permutation = item.product.get_permutation_selected()
|
||||
if not permutation.is_available:
|
||||
ids_permutation.append(permutation.id_permutation)
|
||||
return ids_permutation
|
||||
@@ -1,98 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Delivery Option Business Object
|
||||
|
||||
Description:
|
||||
Business object for delivery option
|
||||
"""
|
||||
|
||||
# internal
|
||||
from extensions import db
|
||||
|
||||
|
||||
# CLASSES
|
||||
"""
|
||||
class Delivery_Option():
|
||||
name: str
|
||||
delay_min: int # days
|
||||
delay_max: int
|
||||
quantity_min: float
|
||||
quantity_max: float
|
||||
regions: list # [Enum_Region]
|
||||
cost: float
|
||||
|
||||
def __new__(cls, name, delay_min, delay_max, quantity_min, quantity_max, regions, cost):
|
||||
_m = 'Delivery_Option.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_str(name, 'name', _m, v_arg_type = v_arg_type)
|
||||
av.val_int(delay_min, 'delay_min', _m, 0, v_arg_type = v_arg_type)
|
||||
av.val_int(delay_max, 'delay_max', _m, 0, v_arg_type = v_arg_type)
|
||||
av.val_float(quantity_min, 'quantity_min', _m, 0, v_arg_type = v_arg_type)
|
||||
av.val_float(quantity_max, 'quantity_max', _m, 0, v_arg_type = v_arg_type)
|
||||
av.val_list_instances(regions, 'regions', _m, Enum_Region, v_arg_type = v_arg_type)
|
||||
av.val_float(cost, 'cost', _m, 0, v_arg_type = v_arg_type)
|
||||
return super(Delivery_Option, cls).__new__(cls)
|
||||
|
||||
def __init__(self, name, delay_min, delay_max, quantity_min, quantity_max, regions, cost):
|
||||
self.name = name
|
||||
self.delay_min = delay_min
|
||||
self.delay_max = delay_max
|
||||
self.quantity_min = quantity_min
|
||||
self.quantity_max = quantity_max
|
||||
self.regions = regions
|
||||
self.cost = cost
|
||||
"""
|
||||
class Delivery_Option(db.Model):
|
||||
id_option = db.Column(db.Integer, primary_key=True)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
code = db.Column(db.String(50))
|
||||
name = db.Column(db.String(100))
|
||||
latency_min = db.Column(db.Integer)
|
||||
latency_max = db.Column(db.Integer)
|
||||
quantity_min = db.Column(db.Integer)
|
||||
quantity_max = db.Column(db.Integer)
|
||||
codes_region = db.Column(db.String(4000))
|
||||
names_region = db.Column(db.String(4000))
|
||||
price_GBP = db.Column(db.Float)
|
||||
display_order = db.Column(db.Integer)
|
||||
def __init__(self):
|
||||
self.delivery_regions = []
|
||||
def from_DB_get_many_product_catalogue(query_row):
|
||||
option = Delivery_Option()
|
||||
option.id_option = query_row[0]
|
||||
option.id_product = query_row[1]
|
||||
option.id_permutation = query_row[2]
|
||||
option.id_category = query_row[3]
|
||||
option.code = query_row[4]
|
||||
option.name = query_row[5]
|
||||
option.latency_min = query_row[6]
|
||||
option.latency_max = query_row[7]
|
||||
option.quantity_min = query_row[8]
|
||||
option.quantity_max = query_row[9]
|
||||
option.codes_region = query_row[10]
|
||||
option.names_region = query_row[11]
|
||||
option.price_GBP = query_row[12]
|
||||
option.display_order = query_row[13]
|
||||
return option
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_option}
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
name: {self.name}
|
||||
code: {self.code}
|
||||
latency_min: {self.latency_min}
|
||||
latency_max: {self.latency_max}
|
||||
quantity_min: {self.quantity_min}
|
||||
quantity_max: {self.quantity_max}
|
||||
codes_region: {self.codes_region}
|
||||
names_region: {self.names_region}
|
||||
price_GBP: {self.price_GBP}
|
||||
display_order: {self.display_order}
|
||||
'''
|
||||
@@ -1,75 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Discount Business Object
|
||||
|
||||
Description:
|
||||
Business object for discount
|
||||
"""
|
||||
|
||||
# internal
|
||||
from extensions import db
|
||||
|
||||
|
||||
# CLASSES
|
||||
class Discount(db.Model):
|
||||
id_discount = db.Column(db.Integer, primary_key=True)
|
||||
id_category = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
code = db.Column(db.String(50))
|
||||
name = db.Column(db.String(200))
|
||||
multiplier = db.Column(db.Float)
|
||||
subtractor = db.Column(db.Float)
|
||||
apply_multiplier_first = db.Column(db.Boolean)
|
||||
quantity_min = db.Column(db.Integer)
|
||||
quantity_max = db.Column(db.Integer)
|
||||
date_start = db.Column(db.DateTime)
|
||||
date_end = db.Column(db.DateTime)
|
||||
codes_region = db.Column(db.String(4000))
|
||||
names_region = db.Column(db.String(4000))
|
||||
codes_currency = db.Column(db.String(4000))
|
||||
names_currency = db.Column(db.String(4000))
|
||||
display_order = db.Column(db.Integer)
|
||||
|
||||
def __init__(self):
|
||||
self.delivery_regions = []
|
||||
def from_DB_get_many_product_catalogue(query_row):
|
||||
discount = Discount()
|
||||
discount.id_discount = query_row[0]
|
||||
discount.id_category = query_row[1]
|
||||
discount.id_product = query_row[2]
|
||||
discount.id_permutation = query_row[3]
|
||||
discount.code = query_row[4]
|
||||
discount.name = query_row[5]
|
||||
discount.multiplier = query_row[6]
|
||||
discount.subtractor = query_row[7]
|
||||
discount.apply_multiplier_first = query_row[8]
|
||||
discount.quantity_min = query_row[9]
|
||||
discount.quantity_max = query_row[10]
|
||||
discount.date_start = query_row[11]
|
||||
discount.date_end = query_row[12]
|
||||
discount.codes_region = query_row[13]
|
||||
discount.names_region = query_row[14]
|
||||
discount.codes_currency = query_row[15]
|
||||
discount.names_currency = query_row[16]
|
||||
discount.display_order = query_row[17]
|
||||
return discount
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_discount}
|
||||
id_category: {self.id_category}
|
||||
id_product: {self.id_product}
|
||||
name: {self.name}
|
||||
code: {self.code}
|
||||
multiplier: {self.multiplier}
|
||||
quantity_min: {self.quantity_min}
|
||||
quantity_max: {self.quantity_max}
|
||||
date_start: {self.date_start}
|
||||
date_end: {self.date_end}
|
||||
display_order: {self.display_order}
|
||||
'''
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Image Business Object
|
||||
|
||||
Description:
|
||||
Business object for product image
|
||||
"""
|
||||
|
||||
# internal
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
import lib.argument_validation as av
|
||||
# external
|
||||
from enum import Enum
|
||||
from typing import ClassVar
|
||||
|
||||
|
||||
class Resolution_Level_Enum(Enum):
|
||||
THUMBNAIL = 0
|
||||
LOW = 1
|
||||
HIGH = 2
|
||||
FULL = 3
|
||||
|
||||
def text(self):
|
||||
return Resolution_Level_Enum.Resolution_Level_Enum_Text(self)
|
||||
|
||||
def Resolution_Level_Enum_Text(category):
|
||||
av.val_instance(category, 'category', 'Resolution_Level_Enum_Text', Resolution_Level_Enum)
|
||||
if category == Resolution_Level_Enum.THUMBNAIL:
|
||||
return 'Thumbnail'
|
||||
elif category == Resolution_Level_Enum.LOW:
|
||||
return 'Low resolution'
|
||||
elif category == Resolution_Level_Enum.HIGH:
|
||||
return 'High resolution'
|
||||
elif category == Resolution_Level_Enum.FULL:
|
||||
return 'Full resolution'
|
||||
else:
|
||||
return 'Unknown'
|
||||
|
||||
def get_member_by_text(text):
|
||||
for member in Resolution_Level_Enum.__members__.values():
|
||||
if member.name == text:
|
||||
return member
|
||||
return Resolution_Level_Enum.HIGH
|
||||
|
||||
|
||||
class Image(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'url'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = 'id_image'
|
||||
id_image = db.Column(db.Integer, primary_key=True)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
url = db.Column(db.String(255))
|
||||
active = db.Column(db.Boolean)
|
||||
display_order = db.Column(db.Integer)
|
||||
"""
|
||||
def __new__(cls, id, id_product, id_category, url, display_order):
|
||||
_m = 'Image.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_int(id, 'id', _m, 0, v_arg_type=v_arg_type)
|
||||
av.val_int(id_product, 'id_product', _m, 0, v_arg_type=v_arg_type)
|
||||
av.val_int(id_category, 'id_category', _m, 0, v_arg_type=v_arg_type)
|
||||
av.val_str(url, 'url', _m, max_len=254, v_arg_type=v_arg_type)
|
||||
av.val_int(display_order, 'display_order', _m, v_arg_type=v_arg_type)
|
||||
return super(Image, cls).__new__(cls)
|
||||
|
||||
def __init__(self, id, id_product, id_category, url, display_order):
|
||||
self.id_image = id
|
||||
self.id_product = id_product
|
||||
self.id_category = id_category
|
||||
self.url = url
|
||||
self.display_order = display_order
|
||||
super().__init__()
|
||||
"""
|
||||
def from_DB_get_many_product_catalogue(query_row):
|
||||
_m = 'Image.from_DB_get_many_product_catalogue'
|
||||
# Helper_App.console_log(f'image: {query_row}')
|
||||
image = Image()
|
||||
image.id_image = query_row[0]
|
||||
image.id_product = query_row[1]
|
||||
image.id_permutation = query_row[2]
|
||||
image.id_category = query_row[3]
|
||||
image.url = query_row[4]
|
||||
image.active = query_row[5]
|
||||
image.display_order = query_row[6]
|
||||
return image
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_image}
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
url: {self.url}
|
||||
display_order: {self.display_order}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_PRODUCT_IMAGE: self.id_image,
|
||||
self.ATTR_ID_PRODUCT: self.id_product,
|
||||
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
|
||||
self.FLAG_URL: self.url,
|
||||
self.FLAG_DISPLAY_ORDER: self.display_order
|
||||
}
|
||||
|
||||
|
||||
class Product_Image_Filters():
|
||||
product_id: int
|
||||
get_thumbnail: bool
|
||||
get_remaining_LQ: bool
|
||||
|
||||
def __new__(cls, product_id, get_thumbnail, get_remaining_LQ):
|
||||
# Initialiser - validation
|
||||
_m = 'Parameters_Product.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_int(product_id, 'product_id', _m, v_arg_type=v_arg_type)
|
||||
av.val_bool(get_thumbnail, 'get_thumbnail', _m, v_arg_type=v_arg_type)
|
||||
av.val_bool(get_remaining_LQ, 'get_remaining_LQ', _m, v_arg_type=v_arg_type)
|
||||
return super(Product, cls).__new__(cls)
|
||||
|
||||
def __init__(self, product_id, get_thumbnail, get_remaining_LQ):
|
||||
# Constructor
|
||||
self.product_id = product_id
|
||||
self.get_thumbnail = get_thumbnail
|
||||
self.get_remaining_LQ = get_remaining_LQ
|
||||
|
||||
@@ -1,354 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Manufacturing_Purchase_Order Business Object
|
||||
|
||||
Description:
|
||||
Business object for manufacturing_purchase_order
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.currency import Currency
|
||||
from business_objects.db_base import Get_Many_Parameters_Base
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from pydantic import BaseModel
|
||||
from typing import ClassVar, Optional
|
||||
from datetime import datetime
|
||||
|
||||
class Manufacturing_Purchase_Order(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_MANUFACTURING_PURCHASE_ORDER
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
|
||||
# __tablename__ = 'Shop_Manufacturing_Purchase_Order_Temp'
|
||||
id_order = db.Column(db.Integer, primary_key=True)
|
||||
id_currency = db.Column(db.Integer)
|
||||
cost_total_local_VAT_excl = db.Column(db.Float)
|
||||
cost_total_local_VAT_incl = db.Column(db.Float)
|
||||
price_total_local_VAT_excl = db.Column(db.Float)
|
||||
price_total_local_VAT_incl = db.Column(db.Float)
|
||||
active = db.Column(db.Boolean)
|
||||
created_on = db.Column(db.DateTime)
|
||||
created_by = db.Column(db.Integer)
|
||||
name = db.Column(db.String(255))
|
||||
# items: list = None
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
self.items = []
|
||||
self.currency = None
|
||||
@classmethod
|
||||
def from_DB_manufacturing_purchase_order(cls, query_row):
|
||||
manufacturing_purchase_order = cls()
|
||||
manufacturing_purchase_order.id_order = query_row[0]
|
||||
manufacturing_purchase_order.id_currency = query_row[1]
|
||||
manufacturing_purchase_order.currency = Currency.from_DB_manufacturing_purchase_order(query_row)
|
||||
manufacturing_purchase_order.cost_total_local_VAT_excl = query_row[4]
|
||||
manufacturing_purchase_order.cost_total_local_VAT_incl = query_row[5]
|
||||
manufacturing_purchase_order.price_total_local_VAT_excl = query_row[6]
|
||||
manufacturing_purchase_order.price_total_local_VAT_incl = query_row[7]
|
||||
manufacturing_purchase_order.active = av.input_bool(query_row[8], 'active', f'{cls.__name__}.from_DB_manufacturing_purchase_order')
|
||||
manufacturing_purchase_order.created_on = query_row[9]
|
||||
manufacturing_purchase_order.name = query_row[10]
|
||||
return manufacturing_purchase_order
|
||||
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.ATTR_ID_MANUFACTURING_PURCHASE_ORDER}: {self.id_order},
|
||||
{self.ATTR_ID_CURRENCY}: {self.id_currency},
|
||||
{self.FLAG_COST_TOTAL_LOCAL_VAT_EXCL}: {self.cost_total_local_VAT_excl},
|
||||
{self.FLAG_COST_TOTAL_LOCAL_VAT_INCL}: {self.cost_total_local_VAT_incl},
|
||||
{self.FLAG_PRICE_TOTAL_LOCAL_VAT_EXCL}: {self.price_total_local_VAT_excl},
|
||||
{self.FLAG_PRICE_TOTAL_LOCAL_VAT_INCL}: {self.price_total_local_VAT_incl},
|
||||
{self.FLAG_ACTIVE}: {self.active},
|
||||
{self.FLAG_CREATED_ON}: {self.created_on},
|
||||
{self.FLAG_NAME}: {self.name}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_MANUFACTURING_PURCHASE_ORDER: self.id_order,
|
||||
self.ATTR_ID_CURRENCY: self.id_currency,
|
||||
self.FLAG_COST_TOTAL_LOCAL_VAT_EXCL: self.cost_total_local_VAT_excl,
|
||||
self.FLAG_COST_TOTAL_LOCAL_VAT_INCL: self.cost_total_local_VAT_incl,
|
||||
self.FLAG_PRICE_TOTAL_LOCAL_VAT_EXCL: self.price_total_local_VAT_excl,
|
||||
self.FLAG_PRICE_TOTAL_LOCAL_VAT_INCL: self.price_total_local_VAT_incl,
|
||||
self.FLAG_ORDER_ITEMS: [item.to_json() for item in self.items],
|
||||
self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'),
|
||||
self.FLAG_CREATED_ON: self.created_on,
|
||||
self.FLAG_NAME: self.name,
|
||||
}
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_order,
|
||||
'text': self.name,
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
|
||||
manufacturing_purchase_order = cls()
|
||||
manufacturing_purchase_order.id_order = json[cls.ATTR_ID_MANUFACTURING_PURCHASE_ORDER]
|
||||
manufacturing_purchase_order.id_currency = json[cls.ATTR_ID_CURRENCY]
|
||||
manufacturing_purchase_order.cost_total_local_VAT_excl = json.get(cls.FLAG_COST_TOTAL_LOCAL_VAT_EXCL, None)
|
||||
manufacturing_purchase_order.cost_total_local_VAT_incl = json.get(cls.FLAG_COST_TOTAL_LOCAL_VAT_INCL, None)
|
||||
manufacturing_purchase_order.price_total_local_VAT_excl = json.get(cls.FLAG_PRICE_TOTAL_LOCAL_VAT_EXCL, None)
|
||||
manufacturing_purchase_order.price_total_local_VAT_incl = json.get(cls.FLAG_PRICE_TOTAL_LOCAL_VAT_INCL, None)
|
||||
manufacturing_purchase_order.items = [Manufacturing_Purchase_Order_Product_Link.from_json(item) for item in json[cls.FLAG_ORDER_ITEMS]]
|
||||
manufacturing_purchase_order.active = json[cls.FLAG_ACTIVE]
|
||||
manufacturing_purchase_order.created_on = json.get(cls.FLAG_CREATED_ON, None)
|
||||
manufacturing_purchase_order.name = json.get(cls.FLAG_NAME, None)
|
||||
return manufacturing_purchase_order
|
||||
def get_items_preview_str(self):
|
||||
preview = ''
|
||||
if self.items is not None:
|
||||
for item in self.items:
|
||||
if preview != '':
|
||||
preview += '\n'
|
||||
preview += f'{item.name_permutation}{f" -(x{item.quantity_used})" if item.quantity_used > 0 else ""}{f" +(x{item.quantity_produced})" if item.quantity_produced > 0 else ""}'
|
||||
return preview
|
||||
|
||||
class Manufacturing_Purchase_Order_Product_Link(db.Model, Store_Base):
|
||||
FLAG_QUANTITY_PRODUCED: ClassVar[str] = 'quantity_produced'
|
||||
FLAG_QUANTITY_USED: ClassVar[str] = 'quantity_used'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_MANUFACTURING_PURCHASE_ORDER_PRODUCT_LINK
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
|
||||
# __tablename__ = 'Shop_Manufacturing_Purchase_Order_Temp'
|
||||
id_link = db.Column(db.Integer, primary_key=True)
|
||||
id_order = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
id_unit_quantity = db.Column(db.Integer)
|
||||
name_permutation = db.Column(db.String(255))
|
||||
csv_id_pairs_variation = db.Column(db.String(4000))
|
||||
quantity_used = db.Column(db.Float)
|
||||
quantity_produced = db.Column(db.Float)
|
||||
id_unit_latency_manufacture = db.Column(db.Integer)
|
||||
latency_manufacture = db.Column(db.Integer)
|
||||
display_order = db.Column(db.Integer)
|
||||
cost_unit_local_VAT_excl = db.Column(db.Float)
|
||||
cost_unit_local_VAT_incl = db.Column(db.Float)
|
||||
price_unit_local_VAT_excl = db.Column(db.Float)
|
||||
price_unit_local_VAT_incl = db.Column(db.Float)
|
||||
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)
|
||||
@classmethod
|
||||
def from_DB_manufacturing_purchase_order(cls, query_row):
|
||||
link = cls()
|
||||
link.id_link = query_row[0]
|
||||
link.id_order = query_row[1]
|
||||
link.id_category = query_row[2]
|
||||
link.id_product = query_row[3]
|
||||
link.id_permutation = query_row[4]
|
||||
link.name_permutation = query_row[5]
|
||||
link.csv_id_pairs_variation = query_row[6]
|
||||
link.id_unit_quantity = query_row[7]
|
||||
link.quantity_used = query_row[8]
|
||||
link.quantity_produced = query_row[9]
|
||||
link.id_unit_latency_manufacture = query_row[10]
|
||||
link.latency_manufacture = query_row[11]
|
||||
link.display_order = query_row[12]
|
||||
link.cost_unit_local_VAT_excl = query_row[13]
|
||||
link.cost_unit_local_VAT_incl = query_row[14]
|
||||
link.price_unit_local_VAT_excl = query_row[15]
|
||||
link.price_unit_local_VAT_incl = query_row[16]
|
||||
link.active = query_row[17]
|
||||
return link
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.ATTR_ID_MANUFACTURING_PURCHASE_ORDER_PRODUCT_LINK}: {self.id_link},
|
||||
{self.ATTR_ID_MANUFACTURING_PURCHASE_ORDER}: {self.id_order},
|
||||
{self.ATTR_ID_PRODUCT_CATEGORY}: {self.id_category},
|
||||
{self.ATTR_ID_PRODUCT}: {self.id_product},
|
||||
{self.ATTR_ID_PRODUCT_PERMUTATION}: {self.id_permutation},
|
||||
{self.FLAG_NAME}: {self.name_permutation},
|
||||
{self.FLAG_PRODUCT_VARIATIONS}: {self.csv_id_pairs_variation},
|
||||
{self.ATTR_ID_UNIT_MEASUREMENT_QUANTITY}: {self.id_unit_quantity},
|
||||
{self.FLAG_QUANTITY_USED}: {self.quantity_used},
|
||||
{self.FLAG_QUANTITY_PRODUCED}: {self.quantity_produced},
|
||||
{self.ATTR_ID_UNIT_MEASUREMENT_LATENCY_MANUFACTURE}: {self.id_unit_latency_manufacture},
|
||||
{self.FLAG_LATENCY_MANUFACTURE}: {self.latency_manufacture},
|
||||
{self.FLAG_DISPLAY_ORDER}: {self.display_order},
|
||||
{self.FLAG_COST_UNIT_LOCAL_VAT_EXCL}: {self.cost_unit_local_VAT_excl},
|
||||
{self.FLAG_COST_UNIT_LOCAL_VAT_INCL}: {self.cost_unit_local_VAT_incl},
|
||||
{self.FLAG_PRICE_UNIT_LOCAL_VAT_EXCL}: {self.price_unit_local_VAT_excl},
|
||||
{self.FLAG_PRICE_UNIT_LOCAL_VAT_INCL}: {self.price_unit_local_VAT_incl},
|
||||
{self.FLAG_ACTIVE}: {self.active}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_MANUFACTURING_PURCHASE_ORDER_PRODUCT_LINK: self.id_link,
|
||||
self.ATTR_ID_MANUFACTURING_PURCHASE_ORDER: self.id_order,
|
||||
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
|
||||
self.ATTR_ID_PRODUCT: self.id_product,
|
||||
self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation,
|
||||
self.FLAG_NAME: self.name_permutation,
|
||||
self.FLAG_PRODUCT_VARIATIONS: self.csv_id_pairs_variation,
|
||||
self.ATTR_ID_UNIT_MEASUREMENT_QUANTITY: self.id_unit_quantity,
|
||||
self.FLAG_QUANTITY_USED: self.quantity_used,
|
||||
self.FLAG_QUANTITY_PRODUCED: self.quantity_produced,
|
||||
self.ATTR_ID_UNIT_MEASUREMENT_LATENCY_MANUFACTURE: self.id_unit_latency_manufacture,
|
||||
self.FLAG_LATENCY_MANUFACTURE: self.latency_manufacture,
|
||||
self.FLAG_DISPLAY_ORDER: self.display_order,
|
||||
self.FLAG_COST_UNIT_LOCAL_VAT_EXCL: self.cost_unit_local_VAT_excl,
|
||||
self.FLAG_COST_UNIT_LOCAL_VAT_INCL: self.cost_unit_local_VAT_incl,
|
||||
self.FLAG_PRICE_UNIT_LOCAL_VAT_EXCL: self.price_unit_local_VAT_excl,
|
||||
self.FLAG_PRICE_UNIT_LOCAL_VAT_INCL: self.price_unit_local_VAT_incl,
|
||||
self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'),
|
||||
}
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_order,
|
||||
'text': self.name_permutation,
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
|
||||
link = cls()
|
||||
link.id_link = json[cls.ATTR_ID_MANUFACTURING_PURCHASE_ORDER_PRODUCT_LINK]
|
||||
link.id_order = json[cls.ATTR_ID_MANUFACTURING_PURCHASE_ORDER]
|
||||
link.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
|
||||
link.id_product = json[cls.ATTR_ID_PRODUCT]
|
||||
link.id_permutation = json.get(cls.ATTR_ID_PRODUCT_PERMUTATION, None)
|
||||
link.name_permutation = json.get(cls.FLAG_NAME, None)
|
||||
link.csv_id_pairs_variation = json[cls.FLAG_PRODUCT_VARIATIONS]
|
||||
link.id_unit_quantity = json[cls.ATTR_ID_UNIT_MEASUREMENT_QUANTITY]
|
||||
link.quantity_used = json[cls.FLAG_QUANTITY_USED]
|
||||
link.quantity_produced = json[cls.FLAG_QUANTITY_PRODUCED]
|
||||
link.id_unit_latency_manufacture = json[cls.ATTR_ID_UNIT_MEASUREMENT_LATENCY_MANUFACTURE]
|
||||
link.latency_manufacture = json[cls.FLAG_LATENCY_MANUFACTURE]
|
||||
link.display_order = json[cls.FLAG_DISPLAY_ORDER]
|
||||
link.cost_unit_local_VAT_excl = json.get(cls.FLAG_COST_UNIT_LOCAL_VAT_EXCL, None)
|
||||
link.cost_unit_local_VAT_incl = json.get(cls.FLAG_COST_UNIT_LOCAL_VAT_INCL, None)
|
||||
link.active = json[cls.FLAG_ACTIVE]
|
||||
return link
|
||||
|
||||
class Parameters_Manufacturing_Purchase_Order(Get_Many_Parameters_Base):
|
||||
a_get_all_order: bool
|
||||
a_get_inactive_order: bool
|
||||
a_ids_order: str
|
||||
a_ids_permutation: str
|
||||
a_date_from: Optional[datetime]
|
||||
a_date_to: Optional[datetime]
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
return cls(
|
||||
a_get_all_order = True,
|
||||
a_get_inactive_order = False,
|
||||
a_ids_order = '',
|
||||
a_ids_permutation = '',
|
||||
a_date_from = None,
|
||||
a_date_to = None
|
||||
)
|
||||
@classmethod
|
||||
def from_filters_manufacturing_purchase_order(cls, form):
|
||||
parameters = cls.get_default()
|
||||
parameters.a_get_inactive_order = form.active.data
|
||||
parameters.a_date_from = form.date_from.data
|
||||
parameters.a_date_to = form.date_to.data
|
||||
return parameters
|
||||
|
||||
class Manufacturing_Purchase_Order_Temp(db.Model, Store_Base):
|
||||
__tablename__: ClassVar[str] = 'Shop_Manufacturing_Purchase_Order_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_order: int = db.Column(db.Integer)
|
||||
id_currency: int = db.Column(db.Integer)
|
||||
active: bool = db.Column(db.Boolean)
|
||||
guid: str = db.Column(db.String(36))
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_manufacturing_purchase_order(cls, manufacturing_purchase_order):
|
||||
row = cls()
|
||||
row.id_order = manufacturing_purchase_order.id_order
|
||||
row.id_currency = manufacturing_purchase_order.id_currency
|
||||
row.active = 1 if manufacturing_purchase_order.active else 0
|
||||
return row
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id_order: {self.id_order}
|
||||
id_currency: {self.id_currency}
|
||||
active: {self.active}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
|
||||
class Manufacturing_Purchase_Order_Product_Link_Temp(db.Model, Store_Base):
|
||||
__tablename__: ClassVar[str] = 'Shop_Manufacturing_Purchase_Order_Product_Link_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_link: int = db.Column(db.Integer)
|
||||
id_order: int = db.Column(db.Integer)
|
||||
# id_category: int = db.Column(db.Integer)
|
||||
id_product: int = db.Column(db.Integer)
|
||||
id_permutation: int = db.Column(db.Integer)
|
||||
csv_list_variations: str = db.Column(db.String)
|
||||
id_unit_quantity: int = db.Column(db.Integer)
|
||||
quantity_used: float = db.Column(db.Float)
|
||||
quantity_produced: float = db.Column(db.Float)
|
||||
id_unit_latency_manufacture = db.Column(db.Integer)
|
||||
latency_manufacture: int = db.Column(db.Integer)
|
||||
display_order: int = db.Column(db.Integer)
|
||||
"""
|
||||
cost_unit_local_VAT_excl: float = db.Column(db.Float)
|
||||
cost_unit_local_VAT_incl: float = db.Column(db.Float)
|
||||
price_unit_local_VAT_excl: float = db.Column(db.Float)
|
||||
price_unit_local_VAT_incl: float = db.Column(db.Float)
|
||||
"""
|
||||
active: bool = db.Column(db.Boolean)
|
||||
guid: str = db.Column(db.String(36))
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_manufacturing_purchase_order_product_link(cls, manufacturing_purchase_order_product_link):
|
||||
row = cls()
|
||||
row.id_link = manufacturing_purchase_order_product_link.id_link
|
||||
row.id_order = manufacturing_purchase_order_product_link.id_order
|
||||
# row.id_category = manufacturing_purchase_order_product_link.id_category
|
||||
row.id_product = manufacturing_purchase_order_product_link.id_product
|
||||
row.id_permutation = manufacturing_purchase_order_product_link.id_permutation
|
||||
row.csv_list_variations = manufacturing_purchase_order_product_link.csv_id_pairs_variation
|
||||
row.id_unit_quantity = manufacturing_purchase_order_product_link.id_unit_quantity
|
||||
row.quantity_used = manufacturing_purchase_order_product_link.quantity_used
|
||||
row.quantity_produced = manufacturing_purchase_order_product_link.quantity_produced
|
||||
row.id_unit_latency_manufacture = manufacturing_purchase_order_product_link.id_unit_latency_manufacture
|
||||
row.latency_manufacture = manufacturing_purchase_order_product_link.latency_manufacture
|
||||
row.display_order = manufacturing_purchase_order_product_link.display_order
|
||||
"""
|
||||
row.cost_unit_local_VAT_excl = manufacturing_purchase_order_product_link.cost_unit_local_VAT_excl
|
||||
row.cost_unit_local_VAT_incl = manufacturing_purchase_order_product_link.cost_unit_local_VAT_incl
|
||||
row.price_unit_local_VAT_excl = manufacturing_purchase_order_product_link.price_unit_local_VAT_excl
|
||||
row.price_unit_local_VAT_incl = manufacturing_purchase_order_product_link.price_unit_local_VAT_incl
|
||||
"""
|
||||
row.active = 1 if manufacturing_purchase_order_product_link.active else 0
|
||||
return row
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id_link: {self.id_link}
|
||||
id_order: {self.id_order}
|
||||
id_product: {self.id_product}
|
||||
id_permutation: {self.id_permutation}
|
||||
csv_list_variations: {self.csv_list_variations}
|
||||
id_unit_quantity: {self.id_unit_quantity}
|
||||
quantity_used: {self.quantity_used}
|
||||
quantity_produced: {self.quantity_produced}
|
||||
{self.ATTR_ID_UNIT_MEASUREMENT_LATENCY_MANUFACTURE}: {self.id_unit_latency_manufacture}
|
||||
latency_manufacture: {self.latency_manufacture}
|
||||
display_order: {self.display_order}
|
||||
active: {self.active}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
@@ -1,89 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Order Business Object
|
||||
|
||||
Description:
|
||||
Business object for order
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
# from lib import data_types
|
||||
from business_objects.store.product import Product
|
||||
from business_objects.store.delivery_option import Delivery_Option
|
||||
from business_objects.store.store_base import Store_Base
|
||||
# from forms import Form_Product
|
||||
# from models.model_view_store import Model_View_Store # circular
|
||||
# external
|
||||
# from enum import Enum
|
||||
from flask import jsonify
|
||||
import locale
|
||||
|
||||
|
||||
# VARIABLE INSTANTIATION
|
||||
|
||||
# CLASSES
|
||||
class Order(Store_Base):
|
||||
category: str
|
||||
product: Product
|
||||
quantity: int
|
||||
subtotal: float
|
||||
delivery_option: Delivery_Option
|
||||
# form: Form_Product
|
||||
|
||||
def __new__(cls, category, product, quantity):
|
||||
# Initialiser - validation
|
||||
_m = 'Product.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_str(category, 'category', _m, v_arg_type=v_arg_type)
|
||||
av.val_instance(product, 'product', _m, Product, v_arg_type=v_arg_type)
|
||||
av.full_val_float(quantity, 'quantity', _m, product.quantity_min, v_arg_type=v_arg_type)
|
||||
return super(Basket_Item, cls).__new__(cls)
|
||||
|
||||
def __init__(self, category, product, quantity):
|
||||
# Constructor
|
||||
self.category = category
|
||||
self.product = product
|
||||
self.quantity = quantity
|
||||
self.subtotal = round(self.product.price_GBP_full * self.quantity, 2)
|
||||
"""
|
||||
self.form = Form_Product()
|
||||
if self.form.validate_on_submit():
|
||||
# Handle form submission
|
||||
|
||||
pass
|
||||
"""
|
||||
|
||||
def update_quantity(self, quantity):
|
||||
_m = 'Basket_Item.update_quantity'
|
||||
v_arg_type = 'class attribute'
|
||||
av.full_val_float(quantity, 'quantity', _m, self.product.quantity_min, v_arg_type=v_arg_type)
|
||||
self.quantity = quantity
|
||||
self.subtotal = round(self.product.price_GBP_full * self.quantity, 2)
|
||||
|
||||
def jsonify(self):
|
||||
return jsonify(self)
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
'product_id': self.product.id_product,
|
||||
'price': self.product.price_GBP_full,
|
||||
'quantity': self.quantity
|
||||
}
|
||||
|
||||
def output_subtotal(self):
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
return locale.format_string("%d", self.subtotal, grouping=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
category: {self.category}
|
||||
product: {self.product}
|
||||
quantity: {self.quantity}
|
||||
subtotal: {self.subtotal}
|
||||
'''
|
||||
@@ -1,93 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Plant Business Object
|
||||
|
||||
Description:
|
||||
Business object for plant
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.address import Address
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from typing import ClassVar
|
||||
|
||||
|
||||
class Plant(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PLANT
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
|
||||
__tablename__ = 'Shop_Plant'
|
||||
id_plant = db.Column(db.Integer, primary_key=True)
|
||||
code = db.Column(db.String(50))
|
||||
name = db.Column(db.String(255))
|
||||
id_address = db.Column(db.Integer)
|
||||
id_user_manager = db.Column(db.Integer)
|
||||
active = db.Column(db.Boolean)
|
||||
|
||||
# address = None
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
self.address = None
|
||||
@classmethod
|
||||
def from_DB_storage_location(cls, query_row):
|
||||
plant = cls()
|
||||
plant.id_plant = query_row[1]
|
||||
plant.id_address = query_row[2]
|
||||
plant.address = Address.from_DB_storage_location(query_row)
|
||||
return plant
|
||||
@classmethod
|
||||
def from_DB_plant(cls, query_row):
|
||||
plant = cls()
|
||||
plant.id_plant = query_row[0]
|
||||
plant.id_address = query_row[1]
|
||||
plant.address = Address.from_DB_plant(query_row)
|
||||
plant.code = query_row[4]
|
||||
plant.name = query_row[5]
|
||||
plant.active = query_row[6]
|
||||
return plant
|
||||
@classmethod
|
||||
def from_DB_stock_item(cls, query_row):
|
||||
plant = cls()
|
||||
plant.id_plant = query_row[5]
|
||||
plant.code = query_row[10]
|
||||
plant.name = query_row[11]
|
||||
return plant
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.ATTR_ID_PLANT}: {self.id_plant}
|
||||
{self.FLAG_CODE}: {self.code}
|
||||
{self.FLAG_NAME}: {self.name}
|
||||
{self.FLAG_ADDRESS}: {self.address}
|
||||
{self.ATTR_ID_USER_MANAGER}: {self.id_user_manager}
|
||||
{self.FLAG_ACTIVE}: {self.active}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_PLANT: self.id_plant,
|
||||
self.FLAG_CODE: self.code,
|
||||
self.FLAG_NAME: self.name,
|
||||
self.FLAG_ADDRESS: None if self.address is None else self.address.to_json(),
|
||||
self.ATTR_ID_USER_MANAGER: self.id_user_manager,
|
||||
self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
|
||||
plant = cls()
|
||||
plant.id_plant = json[cls.ATTR_ID_PLANT],
|
||||
plant.code = json[cls.FLAG_CODE],
|
||||
plant.name = json[cls.FLAG_NAME],
|
||||
plant.address = Address.from_json(json[cls.FLAG_ADDRESS]),
|
||||
plant.id_user_manager = json[cls.ATTR_ID_USER_MANAGER],
|
||||
plant.active = json[cls.FLAG_ACTIVE]
|
||||
return plant
|
||||
@@ -1,917 +0,0 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms.forms import Form_Basket_Add, Form_Basket_Edit
|
||||
from forms.store.product_permutation import Filters_Product_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
|
||||
from business_objects.store.product_permutation import Product_Permutation
|
||||
from business_objects.store.product_price import Product_Price
|
||||
from business_objects.store.store_base import Store_Base
|
||||
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.base import Form_Base
|
||||
from forms.store.product import Filters_Product
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar, List
|
||||
"""
|
||||
class Enum_Status_Stock(Enum):
|
||||
OUT = 0
|
||||
LOW = 1
|
||||
IN = 99
|
||||
|
||||
def text(self):
|
||||
return Enum_Status_Stock.Enum_Status_Stock_Text(self)
|
||||
|
||||
def Enum_Status_Stock_Text(status):
|
||||
av.val_instance(status, 'category', 'Enum_Status_Stock_Text', Enum_Status_Stock)
|
||||
if status == Enum_Status_Stock.OUT:
|
||||
return 'Out of stock'
|
||||
elif status == Enum_Status_Stock.LOW:
|
||||
return 'Low on stock'
|
||||
else:
|
||||
return 'Fully stocked'
|
||||
|
||||
def get_member_by_text(text):
|
||||
return data_types.get_enum_member_by_text(Enum_Status_Stock, text.upper())
|
||||
|
||||
"""
|
||||
class Product(SQLAlchemy_ABC, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT
|
||||
NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME
|
||||
# FLAG_HAS_VARIATIONS: ClassVar[str] = 'has-variations-product'
|
||||
FLAG_INDEX_PERMUTATION_SELECTED: ClassVar[str] = 'index-permutation-selected'
|
||||
FLAG_PRODUCT_VARIATION_TREES: ClassVar[str] = 'variation-trees'
|
||||
|
||||
id_product = db.Column(db.Integer, primary_key=True)
|
||||
id_category = db.Column(db.Integer)
|
||||
name = db.Column(db.String(255))
|
||||
id_access_level_required = db.Column(db.Integer)
|
||||
active = db.Column(db.Boolean)
|
||||
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
|
||||
|
||||
"""
|
||||
permutations: list = None
|
||||
permutation_index: dict = None
|
||||
variation_trees: list = None
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.permutations = []
|
||||
self.permutation_index = {}
|
||||
self.variation_trees = []
|
||||
self.index_permutation_selected = None
|
||||
self.has_variations = False
|
||||
super().__init__()
|
||||
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_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]
|
||||
product.id_category = query_row[1]
|
||||
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.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):
|
||||
_m = 'Product.from_permutation'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_instance(permutation, 'permutation', _m, Product_Permutation, v_arg_type=v_arg_type)
|
||||
product = Product()
|
||||
product.has_variations = has_variations
|
||||
product.index_permutation_selected = 0
|
||||
product.id_product = permutation.id_product
|
||||
product.id_category = permutation.id_category
|
||||
product.display_order = permutation.display_order
|
||||
product.can_view = permutation.can_view
|
||||
product.can_edit = permutation.can_edit
|
||||
product.can_admin = permutation.can_admin
|
||||
product.permutations.append(permutation)
|
||||
# product.get_variation_trees()
|
||||
return product
|
||||
"""
|
||||
def add_product_permutation(self, permutation):
|
||||
_m = 'Product.add_product_permutation'
|
||||
av.val_instance(permutation, 'permutation', _m, Product_Permutation)
|
||||
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]
|
||||
Helper_App.console_log(f'setting selected permutation for product {self.id_product} to {self.index_permutation_selected}') # :\n{self.permutations[self.index_permutation_selected]}
|
||||
"""
|
||||
def from_permutations(permutations):
|
||||
_m = 'Product.from_permutations'
|
||||
v_arg_type = 'class attribute'
|
||||
if len(permutations) == 0:
|
||||
raise ValueError(av.error_msg_str(permutations, 'permutations', _m, list, v_arg_type=v_arg_type))
|
||||
product = Product()
|
||||
product.has_variations = True
|
||||
product.index_permutation_selected = 0
|
||||
product.id_product = permutations[0].id_product
|
||||
product.id_category = permutations[0].id_category
|
||||
product.display_order = permutations[0].display_order
|
||||
product.can_view = True
|
||||
product.can_edit = True
|
||||
product.can_admin = True
|
||||
for permutation in permutations:
|
||||
product.can_view &= permutation.can_view
|
||||
product.can_edit &= permutation.can_edit
|
||||
product.can_admin &= permutation.can_admin
|
||||
product.permutations.append(permutations)
|
||||
product.get_variation_trees()
|
||||
return product
|
||||
"""
|
||||
def get_variation_trees(self):
|
||||
self.variation_trees = []
|
||||
for index_permutation in range(len(self.permutations)):
|
||||
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):
|
||||
found_variation_tree_match = True
|
||||
break
|
||||
if not found_variation_tree_match and variation_tree is not None:
|
||||
self.variation_trees.append(variation_tree)
|
||||
def from_DB_Stripe_product(query_row):
|
||||
permutation = Product_Permutation.from_DB_Stripe_product(query_row)
|
||||
product = Product.from_permutation(permutation)
|
||||
return product
|
||||
def from_DB_Stripe_price(query_row):
|
||||
permutation = Product_Permutation.from_DB_Stripe_price(query_row)
|
||||
product = Product.from_permutation(permutation)
|
||||
return product
|
||||
"""
|
||||
def from_json(json_basket_item, key_id_product, key_id_permutation):
|
||||
permutation = Product_Permutation.from_json(json_basket_item, key_id_product, key_id_permutation)
|
||||
product = Product.from_permutation(permutation)
|
||||
return product
|
||||
"""
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
product = cls()
|
||||
product.id_product = json[cls.ATTR_ID_PRODUCT]
|
||||
product.display_order = json[cls.FLAG_DISPLAY_ORDER]
|
||||
product.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
|
||||
product.name = json[cls.FLAG_NAME]
|
||||
product.has_variations = av.input_bool(json.get(cls.FLAG_HAS_VARIATIONS, None), cls.FLAG_HAS_VARIATIONS, f'{cls.__name__}.from_json')
|
||||
product.id_access_level_required = json.get(cls.ATTR_ID_ACCESS_LEVEL, None)
|
||||
product.active = 1 if av.input_bool(json[cls.FLAG_ACTIVE], cls.FLAG_ACTIVE, f'{cls.__name__}.from_json') else 0
|
||||
product.can_view = json.get(cls.FLAG_CAN_VIEW, None)
|
||||
product.can_edit = json.get(cls.FLAG_CAN_EDIT, None)
|
||||
product.can_admin = json.get(cls.FLAG_CAN_ADMIN, None)
|
||||
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}
|
||||
active: {self.active}
|
||||
'''
|
||||
"""
|
||||
def get_index_permutation_from_id(self, id_permutation):
|
||||
if id_permutation is None and not self.has_variations:
|
||||
return 0
|
||||
for index_permutation in range(len(self.permutations)):
|
||||
permutation = self.permutations[index_permutation]
|
||||
if permutation.id_permutation == id_permutation:
|
||||
return index_permutation
|
||||
raise ValueError(f"{av.error_msg_str(id_permutation, 'id_permutation', 'Product.get_index_permutation_from_id', int)}\nPermutation ID not found.")
|
||||
"""
|
||||
"""
|
||||
def add_product_variation(self, variation):
|
||||
av.val_instance(variation, 'variation', 'Product.add_product_variation', Product_Variation)
|
||||
# Helper_App.console_log(f'variation: {variation}')
|
||||
index_permutation = self.permutation_index[variation.id_permutation] # self.get_index_permutation_from_id(variation.id_permutation)
|
||||
self.permutations[index_permutation].add_product_variation(variation)
|
||||
"""
|
||||
def add_product_variation_type(self, variation_type):
|
||||
variation = variation_type.variations[0]
|
||||
index_permutation = self.permutation_index[variation.id_permutation]
|
||||
self.permutations[index_permutation].add_product_variation_type(variation_type)
|
||||
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_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_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_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_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]
|
||||
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_permutation_row_list(self):
|
||||
list_rows = []
|
||||
for permutation in self.permutations:
|
||||
list_rows.append(permutation.to_row_permutation())
|
||||
return list_rows
|
||||
"""
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
product = cls()
|
||||
product.id_product = json[cls.ATTR_ID_PRODUCT]
|
||||
product.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
|
||||
product.name = json[cls.FLAG_NAME]
|
||||
product.display_order = json[cls.FLAG_DISPLAY_ORDER]
|
||||
product.can_view = json[cls.FLAG_CAN_VIEW]
|
||||
product.can_edit = json[cls.FLAG_CAN_EDIT]
|
||||
product.can_admin = json[cls.FLAG_CAN_ADMIN]
|
||||
product.has_variations = json[cls.FLAG_HAS_VARIATIONS]
|
||||
product.index_permutation_selected = json[cls.FLAG_INDEX_PERMUTATION_SELECTED]
|
||||
product.permutations = []
|
||||
for json_permutation in json[cls.ATTR_ID_PRODUCT_PERMUTATION]:
|
||||
product.permutations.append(Product_Permutation.from_json(json_permutation))
|
||||
product.variation_trees = []
|
||||
for json_tree in json[cls.FLAG_PRODUCT_VARIATION_TREES]:
|
||||
product.variation_trees.append(Product_Variation_Tree.from_json(json_tree))
|
||||
return product
|
||||
"""
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
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_INDEX_PERMUTATION_SELECTED: self.index_permutation_selected,
|
||||
self.ATTR_ID_PRODUCT_PERMUTATION: [permutation.to_json() for permutation in self.permutations],
|
||||
self.FLAG_PRODUCT_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
|
||||
"""
|
||||
def get_csv_ids_permutation(self):
|
||||
csv = ''
|
||||
for permutation in self.permutations:
|
||||
if csv != '':
|
||||
csv += ','
|
||||
csv += str(permutation.id_permutation)
|
||||
return csv
|
||||
|
||||
|
||||
class Parameters_Product(Get_Many_Parameters_Base):
|
||||
# id_user: str
|
||||
get_all_product_category: bool
|
||||
get_inactive_product_category: bool
|
||||
# get_first_product_category_only: bool
|
||||
ids_product_category: str
|
||||
get_all_product: bool
|
||||
get_inactive_product: bool
|
||||
# get_first_product_only: bool
|
||||
ids_product: str
|
||||
get_all_permutation: bool
|
||||
get_inactive_permutation: bool
|
||||
# get_first_permutation_only: bool
|
||||
ids_permutation: str
|
||||
get_all_image: bool
|
||||
get_inactive_image: bool
|
||||
# get_first_image_only: bool
|
||||
ids_image: str
|
||||
"""
|
||||
get_all_region: bool
|
||||
get_inactive_region: bool
|
||||
get_first_region_only: bool
|
||||
ids_region: str
|
||||
get_all_currency: bool
|
||||
get_inactive_currency: bool
|
||||
get_first_currency_only: bool
|
||||
ids_currency: str
|
||||
get_all_discount: bool
|
||||
get_inactive_discount: bool
|
||||
ids_discount: str
|
||||
"""
|
||||
get_products_quantity_stock_below_min: bool
|
||||
|
||||
def to_json(self):
|
||||
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 Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
|
||||
av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product)
|
||||
has_filter_category = not (form.id_category.data == '0' or form.id_category.data == '' or form.id_category.data is None)
|
||||
is_not_empty = av.input_bool(form.is_not_empty.data, "is_not_empty", "Parameters_Product.from_form_filters_product")
|
||||
active = av.input_bool(form.active.data, "active", "Parameters_Product.from_form_filters_product")
|
||||
return Parameters_Product(
|
||||
get_all_product_category = not has_filter_category,
|
||||
get_inactive_product_category = not active,
|
||||
# get_first_product_category_only = False,
|
||||
ids_product_category = form.id_category.data if form.id_category.data is not None else '',
|
||||
get_all_product = True,
|
||||
get_inactive_product = not active,
|
||||
# get_first_product_only = False,
|
||||
ids_product = '',
|
||||
get_all_permutation = True,
|
||||
get_inactive_permutation = not active,
|
||||
# get_first_permutation_only = False,
|
||||
ids_permutation = '',
|
||||
get_all_image = False,
|
||||
get_inactive_image = False,
|
||||
# get_first_image_only = False,
|
||||
ids_image = '',
|
||||
# get_all_region = False,
|
||||
# get_inactive_region = False,
|
||||
# get_first_region_only = False,
|
||||
# ids_region = '',
|
||||
# get_all_currency = False,
|
||||
# get_inactive_currency = False,
|
||||
# get_first_currency_only = False,
|
||||
# ids_currency = '',
|
||||
# get_all_discount = False,
|
||||
# get_inactive_discount = False,
|
||||
# ids_discount = '',
|
||||
get_products_quantity_stock_below_min = False
|
||||
)
|
||||
@staticmethod
|
||||
def from_form_filters_product_permutation(form):
|
||||
# if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
|
||||
# av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product_Permutation)
|
||||
has_category_filter = not (form.id_category.data == '0' or form.id_category.data == '' or form.id_category.data is None)
|
||||
has_product_filter = not (form.id_product.data == '0' or form.id_product.data == '' or form.id_product.data is None)
|
||||
get_permutations_stock_below_min = av.input_bool(form.is_out_of_stock.data, "is_out_of_stock", "Parameters_Product.from_form_filters_product_permutation")
|
||||
get_inactive = not av.input_bool(form.active.data, "active", "Parameters_Product.from_form_filters_product_permutation")
|
||||
Helper_App.console_log(f'form question: {type(form.is_out_of_stock)}\nbool interpretted: {get_permutations_stock_below_min}\nform question: {type(form.active)}\nget_inactive:{get_inactive}\ntype form: {type(form)}')
|
||||
return Parameters_Product(
|
||||
get_all_product_category = not has_category_filter,
|
||||
get_inactive_product_category = get_inactive,
|
||||
# get_first_product_category_only = False,
|
||||
ids_product_category = form.id_category.data if form.id_category.data is not None else '',
|
||||
get_all_product = not has_product_filter,
|
||||
get_inactive_product = get_inactive,
|
||||
# get_first_product_only = False,
|
||||
ids_product = form.id_product.data if form.id_product.data is not None else '',
|
||||
get_all_permutation = not get_permutations_stock_below_min,
|
||||
get_inactive_permutation = get_inactive,
|
||||
# get_first_permutation_only = False,
|
||||
ids_permutation = '',
|
||||
get_all_image = False,
|
||||
get_inactive_image = False,
|
||||
# get_first_image_only = False,
|
||||
ids_image = '',
|
||||
# get_all_region = False,
|
||||
# get_inactive_region = False,
|
||||
# get_first_region_only = False,
|
||||
# ids_region = '',
|
||||
# get_all_currency = False,
|
||||
# get_inactive_currency = False,
|
||||
# get_first_currency_only = False,
|
||||
# ids_currency = '',
|
||||
# get_all_discount = False,
|
||||
# get_inactive_discount = False,
|
||||
# ids_discount = '',
|
||||
get_products_quantity_stock_below_min = get_permutations_stock_below_min
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_default():
|
||||
return Parameters_Product(
|
||||
get_all_product_category = True,
|
||||
get_inactive_product_category = False,
|
||||
# get_first_product_category_only = False,
|
||||
ids_product_category = '',
|
||||
get_all_product = True,
|
||||
get_inactive_product = False,
|
||||
# get_first_product_only = False,
|
||||
ids_product = '',
|
||||
get_all_permutation = True,
|
||||
get_inactive_permutation = False,
|
||||
# get_first_permutation_only = False,
|
||||
ids_permutation = '',
|
||||
get_all_image = True,
|
||||
get_inactive_image = False,
|
||||
# get_first_image_only = False,
|
||||
ids_image = '',
|
||||
# get_all_region = True,
|
||||
# et_inactive_region = False,
|
||||
# get_first_region_only = False,
|
||||
# ids_region = '',
|
||||
# get_all_currency = True,
|
||||
# get_inactive_currency = False,
|
||||
# get_first_currency_only = False,
|
||||
# ids_currency = '',
|
||||
# get_all_discount = True,
|
||||
# get_inactive_discount = False,
|
||||
# ids_discount = '',
|
||||
get_products_quantity_stock_below_min = True
|
||||
)
|
||||
|
||||
@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 = not filters_category.active.data,
|
||||
ids_product_category = '',
|
||||
get_all_product = True,
|
||||
get_inactive_product = False,
|
||||
ids_product = '',
|
||||
get_all_permutation = True,
|
||||
get_inactive_permutation = False,
|
||||
ids_permutation = '',
|
||||
get_all_image = False,
|
||||
get_inactive_image = False,
|
||||
ids_image = '',
|
||||
get_products_quantity_stock_below_min = False
|
||||
)
|
||||
@classmethod
|
||||
def from_filters_stock_item(cls, filters_stock_item):
|
||||
return cls.from_form_filters_product_permutation(filters_stock_item)
|
||||
|
||||
"""
|
||||
class Parameters_Product(Get_Many_Parameters_Base):
|
||||
# id_user: str
|
||||
get_all_product_category: bool
|
||||
get_inactive_product_category: bool
|
||||
# get_first_product_category_only: bool
|
||||
ids_product_category: str
|
||||
get_all_product: bool
|
||||
get_inactive_product: bool
|
||||
# get_first_product_only: bool
|
||||
ids_product: str
|
||||
get_all_permutation: bool
|
||||
get_inactive_permutation: bool
|
||||
# get_first_permutation_only: bool
|
||||
ids_permutation: str
|
||||
get_all_image: bool
|
||||
get_inactive_image: bool
|
||||
# get_first_image_only: bool
|
||||
ids_image: str
|
||||
""
|
||||
get_all_region: bool
|
||||
get_inactive_region: bool
|
||||
get_first_region_only: bool
|
||||
ids_region: str
|
||||
get_all_currency: bool
|
||||
get_inactive_currency: bool
|
||||
get_first_currency_only: bool
|
||||
ids_currency: str
|
||||
get_all_discount: bool
|
||||
get_inactive_discount: bool
|
||||
ids_discount: str
|
||||
""
|
||||
get_products_quantity_stock_below_min: bool
|
||||
|
||||
def __init__(self, a_id_user, **kwargs):
|
||||
super().__init__(a_id_user, **kwargs)
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
'a_id_user': self.a_id_user,
|
||||
'a_get_all_product_category': self.get_all_product_category,
|
||||
'a_get_inactive_product_category': self.get_inactive_product_category,
|
||||
# 'a_get_first_product_category_only': self.get_first_product_category_only,
|
||||
'a_ids_product_category': self.ids_product_category,
|
||||
'a_get_all_product': self.get_all_product,
|
||||
'a_get_inactive_product': self.get_inactive_product,
|
||||
# 'a_get_first_product_only': self.get_first_product_only,
|
||||
'a_ids_product': self.ids_product,
|
||||
'a_get_all_permutation': self.get_all_permutation,
|
||||
'a_get_inactive_permutation': self.get_inactive_permutation,
|
||||
# 'a_get_first_permutation_only': self.get_first_permutation_only,
|
||||
'a_ids_permutation': self.ids_permutation,
|
||||
'a_get_all_image': self.get_all_image,
|
||||
'a_get_inactive_image': self.get_inactive_image,
|
||||
# 'a_get_first_image_only': self.get_first_image_only,
|
||||
'a_ids_image': self.ids_image,
|
||||
# 'a_get_all_delivery_region': self.get_all_region,
|
||||
# 'a_get_inactive_delivery_region': self.get_inactive_region,
|
||||
# 'a_get_first_delivery_region_only': self.get_first_region_only,
|
||||
# 'a_ids_delivery_region': self.ids_region,
|
||||
# 'a_get_all_currency': self.get_all_currency,
|
||||
# 'a_get_inactive_currency': self.get_inactive_currency,
|
||||
# 'a_get_first_currency_only': self.get_first_currency_only,
|
||||
# 'a_ids_currency': self.ids_currency,
|
||||
# 'a_get_all_discount': self.get_all_discount,
|
||||
# 'a_get_inactive_discount': self.get_inactive_discount,
|
||||
# 'a_ids_discount': self.ids_discount,
|
||||
'a_get_products_quantity_stock_below_min': self.get_products_quantity_stock_below_min
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def from_form_filters_product(form, id_user):
|
||||
# if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
|
||||
av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product)
|
||||
has_filter_category = not (form.id_category.data == '0' or form.id_category.data == '')
|
||||
is_not_empty = av.input_bool(form.is_not_empty.data, "is_not_empty", "Parameters_Product.from_form_filters_product")
|
||||
active = av.input_bool(form.active.data, "active", "Parameters_Product.from_form_filters_product")
|
||||
return Parameters_Product(
|
||||
a_id_user = id_user,
|
||||
get_all_product_category = not has_filter_category,
|
||||
get_inactive_product_category = not active,
|
||||
# get_first_product_category_only = False,
|
||||
ids_product_category = str(form.id_category.data),
|
||||
get_all_product = True,
|
||||
get_inactive_product = not active,
|
||||
# get_first_product_only = False,
|
||||
ids_product = '',
|
||||
get_all_permutation = True,
|
||||
get_inactive_permutation = not active,
|
||||
# get_first_permutation_only = False,
|
||||
ids_permutation = '',
|
||||
get_all_image = False,
|
||||
get_inactive_image = False,
|
||||
# get_first_image_only = False,
|
||||
ids_image = '',
|
||||
# get_all_region = False,
|
||||
# get_inactive_region = False,
|
||||
# get_first_region_only = False,
|
||||
# ids_region = '',
|
||||
# get_all_currency = False,
|
||||
# get_inactive_currency = False,
|
||||
# get_first_currency_only = False,
|
||||
# ids_currency = '',
|
||||
# get_all_discount = False,
|
||||
# get_inactive_discount = False,
|
||||
# ids_discount = '',
|
||||
get_products_quantity_stock_below_min = False
|
||||
)
|
||||
@staticmethod
|
||||
def from_form_filters_product_permutation(form):
|
||||
# if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
|
||||
# av.val_instance(form, 'form', 'Parameters_Product.from_form', Form_Base)
|
||||
has_category_filter = not (form.id_category.data is None or form.id_category.data == '0' or form.id_category.data == '')
|
||||
has_product_filter = not (form.id_product.data is None or form.id_product.data == '0' or form.id_product.data == '')
|
||||
get_permutations_stock_below_min = av.input_bool(form.is_out_of_stock.data, "is_out_of_stock", "Parameters_Product.from_form")
|
||||
Helper_App.console_log(f'form question: {type(form.is_out_of_stock)}\nbool interpretted: {get_permutations_stock_below_min}\type form: {type(form)}')
|
||||
return Parameters_Product(
|
||||
get_all_product_category = not has_category_filter,
|
||||
get_inactive_product_category = False,
|
||||
# get_first_product_category_only = False,
|
||||
ids_product_category = str(form.id_category.data) if has_category_filter else '',
|
||||
get_all_product = not has_product_filter,
|
||||
get_inactive_product = False,
|
||||
# get_first_product_only = False,
|
||||
ids_product = str(form.id_product.data) if has_product_filter else '',
|
||||
get_all_permutation = not get_permutations_stock_below_min,
|
||||
get_inactive_permutation = False,
|
||||
# get_first_permutation_only = False,
|
||||
ids_permutation = '',
|
||||
get_all_image = False,
|
||||
get_inactive_image = False,
|
||||
# get_first_image_only = False,
|
||||
ids_image = '',
|
||||
# get_all_region = False,
|
||||
# get_inactive_region = False,
|
||||
# get_first_region_only = False,
|
||||
# ids_region = '',
|
||||
# get_all_currency = False,
|
||||
# get_inactive_currency = False,
|
||||
# get_first_currency_only = False,
|
||||
# ids_currency = '',
|
||||
# get_all_discount = False,
|
||||
# get_inactive_discount = False,
|
||||
# ids_discount = '',
|
||||
get_products_quantity_stock_below_min = get_permutations_stock_below_min
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_default(cls, id_user):
|
||||
return cls(
|
||||
a_id_user = id_user,
|
||||
get_all_product_category = True,
|
||||
get_inactive_product_category = False,
|
||||
# get_first_product_category_only = False,
|
||||
ids_product_category = '',
|
||||
get_all_product = True,
|
||||
get_inactive_product = False,
|
||||
# get_first_product_only = False,
|
||||
ids_product = '',
|
||||
get_all_permutation = True,
|
||||
get_inactive_permutation = False,
|
||||
# get_first_permutation_only = False,
|
||||
ids_permutation = '',
|
||||
get_all_image = True,
|
||||
get_inactive_image = False,
|
||||
# get_first_image_only = False,
|
||||
ids_image = '',
|
||||
# get_all_region = True,
|
||||
# et_inactive_region = False,
|
||||
# get_first_region_only = False,
|
||||
# ids_region = '',
|
||||
# get_all_currency = True,
|
||||
# get_inactive_currency = False,
|
||||
# get_first_currency_only = False,
|
||||
# ids_currency = '',
|
||||
# get_all_discount = True,
|
||||
# get_inactive_discount = False,
|
||||
# ids_discount = '',
|
||||
get_products_quantity_stock_below_min = True
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
return cls(
|
||||
get_all_product_category = json.get('a_get_all_product_category', False),
|
||||
get_inactive_product_category = json.get('a_get_inactive_product_category', False),
|
||||
# get_first_product_category_only = json.get('a_get_first_product_category_only', False),
|
||||
ids_product_category = json.get('a_ids_product_category', ''),
|
||||
get_all_product = json.get('a_get_all_product', False),
|
||||
get_inactive_product = json.get('a_get_inactive_product', False),
|
||||
# get_first_product_only = json.get('a_get_first_product_only', False),
|
||||
ids_product = json.get('a_ids_product', ''),
|
||||
get_all_permutation = json.get('a_get_all_permutation', False),
|
||||
get_inactive_permutation = json.get('a_get_inactive_permutation', False),
|
||||
# get_first_permutation_only = json.get('a_get_first_permutation_only', False),
|
||||
ids_permutation = json.get('a_ids_permutation', ''),
|
||||
get_all_image = json.get('a_get_all_image', False),
|
||||
get_inactive_image = json.get('a_get_inactive_image', False),
|
||||
# get_first_image_only = json.get('a_get_first_image_only', False),
|
||||
ids_image = json.get('a_ids_image', ''),
|
||||
# get_all_region = json.get('a_get_all_region', False),
|
||||
# get_inactive_region = json.get('a_get_inactive_region', False),
|
||||
# get_first_region_only = json.get('a_get_first_region_only', False),
|
||||
# ids_region = json.get('a_ids_region', ''),
|
||||
# get_all_currency = json.get('a_get_all_currency', False),
|
||||
# get_inactive_currency = json.get('a_get_inactive_currency', False),
|
||||
# get_first_currency_only = json.get('a_get_first_currency_only', False),
|
||||
# ids_currency = json.get('a_ids_currency', ''),
|
||||
# get_all_discount = json.get('a_get_all_discount', False),
|
||||
# get_inactive_discount = json.get('a_get_inactive_discount', False),
|
||||
# ids_discount = json.get('a_ids_discount', ''),
|
||||
get_products_quantity_stock_below_min = json.get('a_get_products_quantity_stock_below_min', False)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_filters_product_category(cls, filters_category):
|
||||
return cls(
|
||||
get_all_product_category = True,
|
||||
get_inactive_product_category = filters_category.active.data,
|
||||
ids_product_category = '',
|
||||
get_all_product = True,
|
||||
get_inactive_product = False,
|
||||
ids_product = '',
|
||||
get_all_permutation = True,
|
||||
get_inactive_permutation = False,
|
||||
ids_permutation = '',
|
||||
get_all_image = False,
|
||||
get_inactive_image = False,
|
||||
ids_image = '',
|
||||
get_products_quantity_stock_below_min = False
|
||||
)
|
||||
@classmethod
|
||||
def from_filters_stock_item(cls, filters_stock_item):
|
||||
return cls.from_form_filters_product_permutation(filters_stock_item)
|
||||
"""
|
||||
|
||||
class Product_Temp(db.Model, Store_Base):
|
||||
__tablename__ = 'Shop_Product_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_product: int = db.Column(db.Integer)
|
||||
id_category: int = db.Column(db.Integer)
|
||||
name: str = db.Column(db.String(255))
|
||||
has_variations: bool = db.Column(db.Boolean)
|
||||
id_access_level_required: int = db.Column(db.Integer)
|
||||
active: bool = db.Column(db.Boolean)
|
||||
display_order: int = db.Column(db.Integer)
|
||||
guid: str = db.Column(db.BINARY(36))
|
||||
# created_on: datetime = db.Column(db.DateTime)
|
||||
# created_by: int = db.Column(db.Integer)
|
||||
def __init__(self):
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_product(cls, product):
|
||||
row = cls()
|
||||
row.id_product = product.id_product[0] if isinstance(product.id_product, tuple) else product.id_product
|
||||
row.id_category = product.id_category[0] if isinstance(product.id_category, tuple) else product.id_category
|
||||
row.name = product.name[0] if isinstance(product.name, tuple) else product.name
|
||||
row.has_variations = product.has_variations
|
||||
row.id_access_level_required = product.id_access_level_required[0] if isinstance(product.id_access_level_required, tuple) else product.id_access_level_required
|
||||
row.active = product.active
|
||||
row.display_order = product.display_order
|
||||
"""
|
||||
row.guid = product.guid
|
||||
row.created_on = product.created_on
|
||||
row.created_by = product.created_by
|
||||
"""
|
||||
return row
|
||||
def to_json(self):
|
||||
return {
|
||||
'id_product': self.id_product,
|
||||
'id_category': self.id_category,
|
||||
'name': self.name,
|
||||
'has_variations': av.input_bool(self.has_variations, self.FLAG_HAS_VARIATIONS, f'{self.__class__.__name__}.to_json'),
|
||||
'id_access_level_required': self.id_access_level_required,
|
||||
'active': av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'),
|
||||
'display_order': self.display_order,
|
||||
'guid': self.guid,
|
||||
}
|
||||
"""
|
||||
'created_on': self.created_on,
|
||||
'created_by': self.created_by
|
||||
"""
|
||||
def __repr__(self):
|
||||
return f'''Product_Temp
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
name: {self.name}
|
||||
has_variations: {self.has_variations}
|
||||
id_access_level_required: {self.id_access_level_required}
|
||||
active: {self.active}
|
||||
display_order: {self.display_order}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
@@ -1,529 +0,0 @@
|
||||
"""
|
||||
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 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.product_variation_type import Product_Variation_Type
|
||||
from business_objects.store.image import Image
|
||||
from business_objects.store.delivery_option import Delivery_Option
|
||||
from business_objects.store.discount import Discount
|
||||
from business_objects.store.stock_item import Stock_Item
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from pydantic import BaseModel
|
||||
from typing import ClassVar
|
||||
|
||||
|
||||
class Product_Category(SQLAlchemy_ABC, Store_Base):
|
||||
FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = 'id_access_level_required'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT_CATEGORY
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
|
||||
|
||||
__tablename__ = 'Shop_Product_Category'
|
||||
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)
|
||||
can_edit = db.Column(db.Boolean)
|
||||
can_admin = db.Column(db.Boolean)
|
||||
created_on = db.Column(db.DateTime)
|
||||
created_by = db.Column(db.Integer)
|
||||
|
||||
"""
|
||||
products: list = None # []
|
||||
product_index: dict = None # {}
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.products = []
|
||||
self.product_index = {}
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
self.name_access_level_required = None
|
||||
@classmethod
|
||||
def from_DB_get_many_product_catalogue(cls, query_row):
|
||||
category = cls()
|
||||
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.name_access_level_required = query_row[5]
|
||||
category.display_order = query_row[6]
|
||||
category.active = av.input_bool(query_row[7], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_get_many_product_catalogue')
|
||||
category.can_view = av.input_bool(query_row[8], cls.FLAG_CAN_VIEW, f'{cls.__name__}.from_DB_get_many_product_catalogue')
|
||||
category.can_edit = av.input_bool(query_row[9], cls.FLAG_CAN_EDIT, f'{cls.__name__}.from_DB_get_many_product_catalogue')
|
||||
category.can_admin = av.input_bool(query_row[10], cls.FLAG_CAN_ADMIN, f'{cls.__name__}.from_DB_get_many_product_catalogue')
|
||||
return category
|
||||
"""
|
||||
def key_product_index_from_ids_product_permutation(id_product, id_permutation):
|
||||
return f'{id_product},{"" if id_permutation is None else id_permutation}'
|
||||
def key_product_index_from_product(product):
|
||||
av.val_instance(product, 'product', 'Category.key_product_index_from_product', Product)
|
||||
return f'{product.id_product},{"" if product.id_permutation is None else product.id_permutation}'
|
||||
"""
|
||||
def get_index_product(self, product):
|
||||
return self.get_index_product_from_id(product.id_product)
|
||||
def get_index_product_from_id(self, id_product):
|
||||
try:
|
||||
return self.product_index[id_product]
|
||||
except:
|
||||
raise KeyError(f'product id: {id_product} not in product index keys: {self.product_index.keys()} with category id: {self.id_category}')
|
||||
def get_index_product_from_id_permutation(self, id_permutation):
|
||||
for product in self.products:
|
||||
try:
|
||||
index_permutation = product.get_index_permutation_from_id(id_permutation)
|
||||
return self.get_index_product(product)
|
||||
except:
|
||||
pass
|
||||
raise KeyError(f'permutation id: {id_permutation} not in category id: {self.id_category}')
|
||||
def add_product(self, product):
|
||||
_m = 'Category.add_product'
|
||||
av.val_instance(product, 'product', _m, Product)
|
||||
# self.product_index.append(len(self.products))
|
||||
# self.product_index[Category.key_product_index_from_ids_product_permutation(product.id_product, product.id_permutation)] = len(self.products)
|
||||
try:
|
||||
self.get_index_product(product)
|
||||
Helper_App.console_log(f'category: {self}')
|
||||
raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.")
|
||||
except KeyError:
|
||||
self.product_index[product.id_product] = len(self.products)
|
||||
self.products.append(product)
|
||||
def add_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_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_product_variation(variation)
|
||||
"""
|
||||
def add_product_variation_type(self, variation_type):
|
||||
av.val_instance(variation_type, 'variation_type', 'Category.add_product_variation_type', Product_Variation_Type)
|
||||
variation = variation_type.variations[0]
|
||||
index_product = self.get_index_product_from_id(variation.id_product)
|
||||
self.products[index_product].add_product_variation_type(variation_type)
|
||||
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_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_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_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_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_product_variation_trees(self):
|
||||
for product in self.products:
|
||||
if product.has_variations:
|
||||
Helper_App.console_log(f'product with id:{product.id_product} has variations')
|
||||
product.get_variation_trees()
|
||||
"""
|
||||
def index_product_from_ids_product_permutation(self, id_product, id_permutation):
|
||||
key = Category.key_product_index_from_ids_product_permutation(id_product, id_permutation)
|
||||
Helper_App.console_log(f'product_index: {self.product_index}')
|
||||
Helper_App.console_log(f'Key Error: {key}')
|
||||
try:
|
||||
return self.product_index[key]
|
||||
except KeyError:
|
||||
pass
|
||||
"""
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_category[0] if isinstance(self.id_category, tuple) else self.id_category}
|
||||
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):
|
||||
Helper_App.console_log(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
|
||||
for product in self.products:
|
||||
if product.is_available():
|
||||
return True
|
||||
return False
|
||||
def to_permutation_row_list(self):
|
||||
list_rows = []
|
||||
for product in self.products:
|
||||
list_rows += product.to_permutation_row_list()
|
||||
return list_rows
|
||||
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.get_shared_json_attributes(self),
|
||||
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,
|
||||
self.FLAG_CAN_EDIT: self.can_edit,
|
||||
self.FLAG_CAN_ADMIN: self.can_admin
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f' Category.from_json: {json}')
|
||||
category = cls()
|
||||
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 = 1 if av.input_bool(json[cls.FLAG_ACTIVE], cls.FLAG_ACTIVE, f'{cls.__name__}.from_json') else 0
|
||||
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
|
||||
}
|
||||
def get_csv_ids_permutation(self):
|
||||
list_ids = []
|
||||
for product in self.products:
|
||||
list_ids += product.get_csv_ids_permutation()
|
||||
return list_ids
|
||||
"""
|
||||
class Filters_Product_Category(BaseModel, Store_Base):
|
||||
ids_product_category: str
|
||||
ids_product: str
|
||||
""
|
||||
def __new__(cls, product_ids, product_categories):
|
||||
_m = 'Parameters_Product.__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(Parameters_Product_Category, cls).__new__(cls)
|
||||
""
|
||||
def __init__(self, ids_product, ids_product_category):
|
||||
super().__init__(ids_product=ids_product, ids_product_category=ids_product_category)
|
||||
""
|
||||
# Constructor
|
||||
self.ids = product_ids
|
||||
self.categories = product_categories
|
||||
""
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
return Filters_Product_Category(
|
||||
ids_product_category = '',
|
||||
ids_product = ''
|
||||
)
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
'a_ids_product_category': self.ids_product_category,
|
||||
'a_ids_product': self.ids_product
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
filters = cls()
|
||||
filters.ids_product_category = json['a_ids_product_category'],
|
||||
filters.ids_product = json['a_ids_product']
|
||||
|
||||
|
||||
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 = False,
|
||||
active = True
|
||||
)
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.FLAG_IS_NOT_EMPTY: self.is_not_empty,
|
||||
self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json')
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
return cls(
|
||||
is_not_empty = json['is_not_empty'],
|
||||
active = json['active']
|
||||
)
|
||||
@classmethod
|
||||
def from_form(cls, form):
|
||||
return cls(
|
||||
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 Product_Category_Container(Store_Base):
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = ''
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.FLAG_ROWS
|
||||
categories: list
|
||||
def __init__(self):
|
||||
self.categories = []
|
||||
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)):
|
||||
category = self.categories[index_category]
|
||||
if category.id_category == id_category:
|
||||
return index_category
|
||||
raise ValueError(f"{av.error_msg_str(id_category, 'id_category', 'Container_Product_Categories.get_index_category_from_id', int)}\nID not in list")
|
||||
def get_index_category_from_id_permutation(self, id_permutation):
|
||||
for index_category in range(len(self.categories)):
|
||||
category = self.categories[index_category]
|
||||
try:
|
||||
index_product = category.get_index_product_from_id_permutation(id_permutation)
|
||||
return index_category
|
||||
except:
|
||||
pass
|
||||
raise ValueError(f"{av.error_msg_str(id_permutation, 'id_permutation', 'Container_Product_Categories.get_index_category_from_id_permutation', int)}. Permutation ID not in list")
|
||||
def add_product(self, product):
|
||||
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_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_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_product_variation(variation)
|
||||
"""
|
||||
def add_product_variation_type(self, variation_type):
|
||||
av.val_instance(variation_type, 'variation_type', 'Container_Product_Categories.add_product_variation_type', Product_Variation_Type)
|
||||
variation = variation_type.variations[0]
|
||||
index_category = self.get_index_category_from_id(variation.id_category)
|
||||
self.categories[index_category].add_product_variation_type(variation_type)
|
||||
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_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_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_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_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_product_variation_trees(self):
|
||||
for category in self.categories:
|
||||
category.get_all_product_variation_trees()
|
||||
def __repr__(self):
|
||||
return f'categories: {self.categories}'
|
||||
"""
|
||||
def get_permutation_first(self):
|
||||
Helper_App.console_log(f'getting first permutation from category list')
|
||||
if not (len(self.categories) == 0):
|
||||
Helper_App.console_log(f'getting first permutation from category')
|
||||
return None if len(self.categories) == 0 else self.categories[0].get_permutation_first()
|
||||
"""
|
||||
def get_category_count(self):
|
||||
return len(self.categories)
|
||||
def to_permutation_row_list(self):
|
||||
list_rows = []
|
||||
for category in self.categories:
|
||||
list_rows += category.to_permutation_row_list()
|
||||
return list_rows
|
||||
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 get_list_products(self):
|
||||
list_products = []
|
||||
for category in self.categories:
|
||||
# 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})
|
||||
"""
|
||||
list_products += category.products
|
||||
return list_products
|
||||
def to_product_option_list(self):
|
||||
list_products = self.get_list_products()
|
||||
return [{'value': product.id_product, 'text': product.name, Product.ATTR_ID_PRODUCT_CATEGORY: product.id_category} for product in list_products]
|
||||
def get_product_option_lists_by_category(self):
|
||||
dict_lists_products = {}
|
||||
for category in self.categories:
|
||||
dict_lists_products[category.id_category] = category.to_product_option_list()
|
||||
return dict_lists_products
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
f'{self.FLAG_ROWS}': [category.to_json() for category in self.categories]
|
||||
}
|
||||
"""
|
||||
def to_json_str(self):
|
||||
return {
|
||||
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)
|
||||
def get_csv_ids_permutation(self):
|
||||
list_ids = []
|
||||
for category in self.categories:
|
||||
list_ids += category.get_csv_ids_permutation()
|
||||
return ','.join(list_ids)
|
||||
|
||||
|
||||
"""
|
||||
class Table_Shop_Product_Category(db.Model):
|
||||
__tablename__ = 'Shop_Product_Category'
|
||||
id_category: int = db.Column(db.Integer, primary_key=True)
|
||||
code: str = db.Column(db.String(50))
|
||||
name: str = db.Column(db.String(255))
|
||||
description: str = db.Column(db.String(4000))
|
||||
active: bool = db.Column(db.Boolean)
|
||||
display_order: int = db.Column(db.Integer)
|
||||
created_on: datetime = db.Column(db.DateTime)
|
||||
created_by: int = db.Column(db.Integer)
|
||||
id_change_set: int = db.Column(db.Integer)
|
||||
"""
|
||||
class Product_Category_Temp(db.Model, Store_Base):
|
||||
__tablename__ = 'Shop_Product_Category_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_category: int = db.Column(db.Integer)
|
||||
code: str = db.Column(db.String(50))
|
||||
name: str = db.Column(db.String(255))
|
||||
description: str = db.Column(db.String(4000))
|
||||
id_access_level_required: int = db.Column(db.Integer)
|
||||
active: bool = db.Column(db.Boolean)
|
||||
display_order: int = db.Column(db.Integer)
|
||||
guid: str = db.Column(db.String(36))
|
||||
# created_on: datetime = db.Column(db.DateTime)
|
||||
# created_by: int = db.Column(db.Integer)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_product_category(cls, product_category):
|
||||
row = cls()
|
||||
row.id_category = product_category.id_category[0] if isinstance(product_category.id_category, tuple) else product_category.id_category
|
||||
row.code = product_category.code[0] if isinstance(product_category.code, tuple) else product_category.code
|
||||
row.name = product_category.name[0] if isinstance(product_category.name, tuple) else product_category.name
|
||||
row.description = product_category.description[0] if isinstance(product_category.description, tuple) else product_category.description
|
||||
row.id_access_level_required = product_category.id_access_level_required[0] if isinstance(product_category.id_access_level_required, tuple) else product_category.id_access_level_required
|
||||
row.active = product_category.active
|
||||
row.display_order = product_category.display_order
|
||||
"""
|
||||
row.guid = product_category.guid
|
||||
row.created_on = product_category.created_on
|
||||
row.created_by = product_category.created_by
|
||||
"""
|
||||
return row
|
||||
def to_json(self):
|
||||
return {
|
||||
'id_category': self.id_category,
|
||||
'code': self.code,
|
||||
'name': self.name,
|
||||
'description': self.description,
|
||||
'id_access_level_required': self.id_access_level_required,
|
||||
'active': av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'),
|
||||
'display_order': self.display_order,
|
||||
'guid': self.guid,
|
||||
}
|
||||
"""
|
||||
'created_on': self.created_on,
|
||||
'created_by': self.created_by
|
||||
"""
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.__dict__)
|
||||
@@ -1,617 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Permutation Business Object
|
||||
|
||||
Description:
|
||||
Business object for product permutation
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms.forms import Form_Basket_Add, Form_Basket_Edit
|
||||
from business_objects.currency import Currency
|
||||
from business_objects.store.delivery_option import Delivery_Option
|
||||
from business_objects.store.discount import Discount
|
||||
from business_objects.store.image import Image
|
||||
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 business_objects.unit_measurement import Unit_Measurement
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar
|
||||
|
||||
class Product_Permutation(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE = Store_Base.ATTR_ID_PRODUCT_PERMUTATION
|
||||
NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME
|
||||
FLAG_CURRENCY_COST = f'{Currency.ATTR_ID_CURRENCY}_cost'
|
||||
FLAG_CODE_CURRENCY_COST = f'{Currency.FLAG_CODE}_cost'
|
||||
FLAG_SYMBOL_CURRENCY_COST = f'{Currency.FLAG_SYMBOL}_cost'
|
||||
FLAG_PROFIT_LOCAL_MIN = 'profit_local_min'
|
||||
FLAG_HAS_VARIATIONS = 'has_variations'
|
||||
FLAG_LATENCY_MANUFACTURE = 'latency_manufacture'
|
||||
FLAG_UNIT_MEASUREMENT_QUANTITY = f'{Unit_Measurement.ATTR_ID_UNIT_MEASUREMENT}_quantity'
|
||||
FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY = f'{Unit_Measurement.FLAG_SYMBOL}_quantity'
|
||||
FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY = f'{Unit_Measurement.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX}_quantity'
|
||||
FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_QUANTITY = f'{Unit_Measurement.FLAG_NAME_SINGULAR}_quantity'
|
||||
FLAG_NAME_PLURAL_UNIT_MEASUREMENT_QUANTITY = f'{Unit_Measurement.FLAG_NAME_PLURAL}_quantity'
|
||||
FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP = 'count_unit_measurement_per_quantity_step'
|
||||
FLAG_QUANTITY_STOCK = 'quantity_stock'
|
||||
FLAG_IS_SUBSCRIPTION = 'is_subscription'
|
||||
FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE = f'{Unit_Measurement.ATTR_ID_UNIT_MEASUREMENT}_interval_recurrence'
|
||||
FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE = f'{Unit_Measurement.FLAG_SYMBOL}_unit_measurement_interval_recurrence'
|
||||
FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE = f'{Unit_Measurement.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX}_unit_measurement_interval_recurrence'
|
||||
FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_RECURRENCE = f'{Unit_Measurement.FLAG_NAME_SINGULAR}_unit_measurement_interval_recurrence'
|
||||
FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE = f'{Unit_Measurement.FLAG_NAME_PLURAL}_unit_measurement_interval_recurrence'
|
||||
FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE = 'count_interval_recurrence'
|
||||
FLAG_ID_STRIPE_PRODUCT = 'id_stripe_product'
|
||||
FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED = 'does_expire_faster_once_unsealed'
|
||||
FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED = f'{Unit_Measurement.ATTR_ID_UNIT_MEASUREMENT}_interval_expiration_unsealed'
|
||||
FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED = f'{Unit_Measurement.FLAG_SYMBOL}_interval_expiration_unsealed'
|
||||
FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_INTERVAL_EXPIRATION_UNSEALED = f'{Unit_Measurement.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX}_interval_expiration_unsealed'
|
||||
FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED = f'{Unit_Measurement.FLAG_NAME_SINGULAR}_interval_expiration_unsealed'
|
||||
FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED = f'{Unit_Measurement.FLAG_NAME_PLURAL}_interval_expiration_unsealed'
|
||||
FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED = 'count_interval_expiration_unsealed'
|
||||
|
||||
id_permutation = db.Column(db.Integer, primary_key=True)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
csv_id_pairs_variation = db.Column(db.String(4000))
|
||||
# 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))
|
||||
"""
|
||||
# currency_cost: Currency
|
||||
cost_local_VAT_excl = db.Column(db.Float)
|
||||
cost_local_VAT_incl = db.Column(db.Float)
|
||||
profit_local_min = db.Column(db.Float)
|
||||
has_variations = db.Column(db.Boolean)
|
||||
latency_manufacture = db.Column(db.Integer)
|
||||
id_unit_measurement_quantity = db.Column(db.Integer)
|
||||
symbol_unit_measurement_quantity = db.Column(db.String(50))
|
||||
symbol_is_suffix_not_prefix_unit_measurement_quantity = db.Column(db.Boolean)
|
||||
name_singular_unit_measurement_quantity = db.Column(db.String(255))
|
||||
name_plural_unit_measurement_quantity = db.Column(db.String(256))
|
||||
count_unit_measurement_per_quantity_step = db.Column(db.Integer)
|
||||
quantity_min = db.Column(db.Float)
|
||||
quantity_max = db.Column(db.Float)
|
||||
quantity_stock = db.Column(db.Float)
|
||||
is_subscription = db.Column(db.Boolean)
|
||||
id_unit_measurement_interval_recurrence = db.Column(db.Integer)
|
||||
symbol_unit_measurement_interval_recurrence = db.Column(db.String(50))
|
||||
symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence = db.Column(db.Boolean)
|
||||
name_singular_unit_measurement_interval_recurrence = db.Column(db.String(255))
|
||||
name_plural_unit_measurement_interval_recurrence = db.Column(db.String(256))
|
||||
count_interval_recurrence = db.Column(db.Integer)
|
||||
id_stripe_product = db.Column(db.String(100))
|
||||
does_expire_faster_once_unsealed = db.Column(db.Boolean)
|
||||
id_unit_measurement_interval_expiration_unsealed = db.Column(db.Integer)
|
||||
symbol_unit_measurement_interval_expiration_unsealed = db.Column(db.String(50))
|
||||
symbol_is_suffix_not_prefix_unit_interval_expiration_unsealed = db.Column(db.Boolean)
|
||||
name_singular_unit_measurement_interval_expiration_unsealed = db.Column(db.String(255))
|
||||
name_plural_unit_measurement_interval_expiration_unsealed = db.Column(db.String(256))
|
||||
count_interval_expiration_unsealed = db.Column(db.Integer)
|
||||
has_variations = db.Column(db.Boolean)
|
||||
active = db.Column(db.Boolean)
|
||||
# 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
|
||||
# variation_tree
|
||||
|
||||
def __init__(self):
|
||||
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__()
|
||||
Store_Base.__init__(self)
|
||||
self.currency_cost = None
|
||||
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
|
||||
self.variation_tree = None
|
||||
# self.variations = []
|
||||
@classmethod
|
||||
def from_DB_get_many_product_catalogue(cls, query_row):
|
||||
_m = f'{cls.__name__}.from_DB_get_many_product_catalogue'
|
||||
v_arg_type = 'class attribute'
|
||||
Helper_App.console_log(f'query_row: {query_row}')
|
||||
permutation = cls()
|
||||
permutation.id_permutation = query_row[0]
|
||||
permutation.id_product = query_row[1]
|
||||
permutation.id_category = query_row[2]
|
||||
permutation.description = query_row[3]
|
||||
permutation.cost_local_VAT_excl = query_row[4]
|
||||
permutation.cost_local_VAT_incl = query_row[5]
|
||||
permutation.currency_cost = Currency.from_DB_get_many_product_catalogue_product_permutation(query_row)
|
||||
permutation.profit_local_min = query_row[9]
|
||||
permutation.latency_manufacture = query_row[10]
|
||||
permutation.id_unit_measurement_quantity = query_row[11]
|
||||
permutation.symbol_unit_measurement_quantity = query_row[12]
|
||||
permutation.symbol_is_suffix_not_prefix_unit_measurement_quantity = av.input_bool(query_row[13], cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY, _m, v_arg_type=v_arg_type)
|
||||
permutation.name_singular_unit_measurement_quantity = query_row[14]
|
||||
permutation.name_plural_unit_measurement_quantity = query_row[15]
|
||||
permutation.count_unit_measurement_per_quantity_step = query_row[16]
|
||||
permutation.quantity_min = query_row[17]
|
||||
permutation.quantity_max = query_row[18]
|
||||
permutation.quantity_stock = query_row[19]
|
||||
permutation.is_subscription = av.input_bool(query_row[20], "is_subscription", _m, v_arg_type=v_arg_type)
|
||||
permutation.id_unit_measurement_interval_recurrence = query_row[21]
|
||||
permutation.symbol_unit_measurement_interval_recurrence = query_row[22]
|
||||
permutation.symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence = av.input_bool(query_row[23], cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE, _m, v_arg_type=v_arg_type)
|
||||
permutation.name_singular_unit_measurement_interval_recurrence = query_row[24]
|
||||
permutation.name_plural_unit_measurement_interval_recurrence = query_row[25]
|
||||
permutation.count_interval_recurrence = query_row[26]
|
||||
permutation.id_stripe_product = query_row[27]
|
||||
permutation.does_expire_faster_once_unsealed = av.input_bool(query_row[28], "does_expire_faster_once_unsealed", _m, v_arg_type=v_arg_type)
|
||||
permutation.id_unit_measurement_interval_expiration_unsealed = query_row[29]
|
||||
permutation.symbol_unit_measurement_interval_expiration_unsealed = query_row[30]
|
||||
permutation.symbol_is_suffix_not_prefix_unit_interval_expiration_unsealed = av.input_bool(query_row[31], cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_INTERVAL_EXPIRATION_UNSEALED, _m, v_arg_type=v_arg_type)
|
||||
permutation.name_singular_unit_measurement_interval_expiration_unsealed = query_row[32]
|
||||
permutation.name_plural_unit_measurement_interval_expiration_unsealed = query_row[33]
|
||||
permutation.count_interval_expiration_unsealed = query_row[34]
|
||||
permutation.has_variations = av.input_bool(query_row[35], cls.FLAG_HAS_VARIATIONS, _m, v_arg_type=v_arg_type)
|
||||
permutation.active = av.input_bool(query_row[36], cls.FLAG_ACTIVE, _m, v_arg_type=v_arg_type)
|
||||
# permutation.display_order = query_row[27]
|
||||
permutation.can_view = av.input_bool(query_row[37], "can_view", _m, v_arg_type=v_arg_type)
|
||||
permutation.can_edit = av.input_bool(query_row[38], "can_edit", _m, v_arg_type=v_arg_type)
|
||||
permutation.can_admin = av.input_bool(query_row[39], "can_admin", _m, v_arg_type=v_arg_type)
|
||||
return permutation
|
||||
|
||||
def from_DB_Stripe_product(query_row):
|
||||
_m = 'Product_Permutation.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 from_DB_Stripe_price(query_row):
|
||||
_m = 'Product_Permutation.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_singular_unit_measurement_interval_recurrence = query_row[4]
|
||||
permutation.count_interval_recurrence = query_row[5]
|
||||
return permutation
|
||||
"""
|
||||
def from_json(json_basket_item, key_id_product, key_id_permutation):
|
||||
_m = 'Product_Permutation.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
|
||||
"""
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
_m = f'{cls.__name__}.from_json'
|
||||
permutation = cls()
|
||||
permutation.id_permutation = json[cls.ATTR_ID_PRODUCT_PERMUTATION]
|
||||
permutation.id_product = json[cls.ATTR_ID_PRODUCT]
|
||||
permutation.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
|
||||
permutation.description = json[cls.FLAG_DESCRIPTION]
|
||||
permutation.cost_local_VAT_excl = json.get(cls.FLAG_COST_UNIT_LOCAL_VAT_EXCL, None)
|
||||
permutation.cost_local_VAT_incl = json.get(cls.FLAG_COST_UNIT_LOCAL_VAT_INCL, None)
|
||||
permutation.currency_cost = Currency.from_json(json, '_cost')
|
||||
permutation.profit_local_min = json[cls.FLAG_PROFIT_LOCAL_MIN]
|
||||
permutation.latency_manufacture = json[cls.FLAG_LATENCY_MANUFACTURE]
|
||||
permutation.id_unit_measurement_quantity = json[cls.FLAG_UNIT_MEASUREMENT_QUANTITY]
|
||||
permutation.symbol_unit_measurement_quantity = json.get(cls.FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY)
|
||||
permutation.symbol_is_suffix_not_prefix_unit_measurement_quantity = json.get(cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY)
|
||||
permutation.name_singular_unit_measurement_quantity = json.get(cls.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_QUANTITY)
|
||||
permutation.name_plural_unit_measurement_quantity = json.get(cls.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_QUANTITY)
|
||||
permutation.count_unit_measurement_per_quantity_step = json[cls.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP]
|
||||
permutation.quantity_min = json[cls.FLAG_QUANTITY_MIN]
|
||||
permutation.quantity_max = json[cls.FLAG_QUANTITY_MAX]
|
||||
permutation.quantity_stock = json[cls.FLAG_QUANTITY_STOCK]
|
||||
permutation.is_subscription = 1 if av.input_bool(json[cls.FLAG_IS_SUBSCRIPTION], cls.FLAG_IS_SUBSCRIPTION, _m) else 0
|
||||
permutation.id_unit_measurement_interval_recurrence = json[cls.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE] if json[cls.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE] != '' else None
|
||||
permutation.symbol_unit_measurement_interval_recurrence = json.get(cls.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE)
|
||||
permutation.symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence = json.get(cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE)
|
||||
permutation.name_singular_unit_measurement_interval_recurrence = json.get(cls.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_RECURRENCE)
|
||||
permutation.name_plural_unit_measurement_interval_recurrence = json.get(cls.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE)
|
||||
permutation.count_interval_recurrence = json[cls.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE] if json[cls.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE] != '' else None
|
||||
permutation.id_stripe_product = json[cls.FLAG_ID_STRIPE_PRODUCT]
|
||||
permutation.does_expire_faster_once_unsealed = 1 if av.input_bool(json[cls.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED], cls.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED, _m) else 0
|
||||
permutation.id_unit_measurement_interval_expiration_unsealed = json[cls.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED] if json[cls.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED] != '' else None
|
||||
permutation.symbol_unit_measurement_interval_expiration_unsealed = json.get(cls.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED)
|
||||
permutation.symbol_is_suffix_not_prefix_unit_interval_expiration_unsealed = json.get(cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_INTERVAL_EXPIRATION_UNSEALED)
|
||||
permutation.name_singular_unit_measurement_interval_expiration_unsealed = json.get(cls.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED)
|
||||
permutation.name_plural_unit_measurement_interval_expiration_unsealed = json.get(cls.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED)
|
||||
permutation.count_interval_expiration_unsealed = json[cls.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED] if json[cls.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED] != '' else None
|
||||
permutation.has_variations = json[cls.FLAG_HAS_VARIATIONS]
|
||||
permutation.active = 1 if av.input_bool(json[cls.FLAG_ACTIVE], cls.FLAG_ACTIVE, _m) else 0
|
||||
if permutation.has_variations:
|
||||
permutation.csv_id_pairs_variation = json[cls.FLAG_PRODUCT_VARIATIONS]
|
||||
permutation.variation_tree = Product_Variation_Tree.from_json_str(permutation.csv_id_pairs_variation)
|
||||
"""
|
||||
for jsonProductVariation in json[cls.FLAG_PRODUCT_VARIATIONS]:
|
||||
variation = Product_Variation.from_json(jsonProductVariation)
|
||||
permutation.add_product_variation(variation)
|
||||
"""
|
||||
return permutation
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation,
|
||||
self.ATTR_ID_PRODUCT: self.id_product,
|
||||
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
|
||||
self.FLAG_DESCRIPTION: self.description,
|
||||
self.FLAG_COST_UNIT_LOCAL_VAT_EXCL: self.cost_local_VAT_excl,
|
||||
self.FLAG_COST_UNIT_LOCAL_VAT_INCL: self.cost_local_VAT_incl,
|
||||
self.FLAG_CURRENCY_COST: self.currency_cost.to_json(),
|
||||
self.FLAG_PROFIT_LOCAL_MIN: self.profit_local_min,
|
||||
self.FLAG_LATENCY_MANUFACTURE: self.latency_manufacture,
|
||||
self.FLAG_UNIT_MEASUREMENT_QUANTITY: self.id_unit_measurement_quantity,
|
||||
self.FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY: self.symbol_unit_measurement_quantity,
|
||||
self.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY: self.symbol_is_suffix_not_prefix_unit_measurement_quantity,
|
||||
self.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_QUANTITY: self.name_singular_unit_measurement_quantity,
|
||||
self.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_QUANTITY: self.name_plural_unit_measurement_quantity,
|
||||
self.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP: self.count_unit_measurement_per_quantity_step,
|
||||
self.FLAG_QUANTITY_MIN: self.quantity_min,
|
||||
self.FLAG_QUANTITY_MAX: self.quantity_max,
|
||||
self.FLAG_QUANTITY_STOCK: self.quantity_stock,
|
||||
self.FLAG_IS_SUBSCRIPTION: self.is_subscription,
|
||||
self.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.id_unit_measurement_interval_recurrence,
|
||||
self.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.symbol_unit_measurement_interval_recurrence,
|
||||
self.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence,
|
||||
self.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.name_singular_unit_measurement_interval_recurrence,
|
||||
self.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.name_plural_unit_measurement_interval_recurrence,
|
||||
self.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.count_interval_recurrence,
|
||||
self.FLAG_ID_STRIPE_PRODUCT: self.id_stripe_product,
|
||||
self.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED: self.does_expire_faster_once_unsealed,
|
||||
self.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.id_unit_measurement_interval_expiration_unsealed,
|
||||
self.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.symbol_unit_measurement_interval_expiration_unsealed,
|
||||
self.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_INTERVAL_EXPIRATION_UNSEALED: self.symbol_is_suffix_not_prefix_unit_interval_expiration_unsealed,
|
||||
self.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.name_singular_unit_measurement_interval_expiration_unsealed,
|
||||
self.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.name_plural_unit_measurement_interval_expiration_unsealed,
|
||||
self.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.count_interval_expiration_unsealed,
|
||||
self.FLAG_HAS_VARIATIONS: self.has_variations,
|
||||
self.FLAG_ACTIVE: self.active,
|
||||
self.FLAG_CAN_VIEW: self.can_view,
|
||||
self.FLAG_CAN_EDIT: self.can_edit,
|
||||
self.FLAG_CAN_ADMIN: self.can_admin,
|
||||
self.FLAG_PRODUCT_VARIATIONS: [] if self.variation_tree is None else [variation_type.to_json() for variation_type in self.variation_tree.get_product_variation_types()],
|
||||
self.FLAG_PRODUCT_IMAGE: [image.to_json() for image in self.images],
|
||||
self.FLAG_DELIVERY_OPTION: [option.to_json() for option in self.delivery_options],
|
||||
self.FLAG_PRODUCT_PRICE: [price.to_json() for price in self.prices],
|
||||
}
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_permutation,
|
||||
'text': self.get_name_variations()
|
||||
}
|
||||
|
||||
def get_name(self):
|
||||
return
|
||||
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):
|
||||
return self.prices[0]
|
||||
|
||||
def output_delivery_date(self):
|
||||
return (datetime.now() + timedelta(days=self.latency_manufacture)).strftime('%A, %d %B %Y')
|
||||
|
||||
"""
|
||||
def output_lead_time(self):
|
||||
return '1 day' if self.latency_manufacture == 1 else f'{self.latency_manufacture} days'
|
||||
|
||||
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_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.id_type}: {variation.id_variation}' for variation in self.variations])
|
||||
"""
|
||||
|
||||
def __repr__(self):
|
||||
return f'''Product_Permutation
|
||||
id_permutation: {self.id_permutation}
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
description: {self.description}
|
||||
cost_local_VAT_excl: {self.cost_local_VAT_excl}
|
||||
cost_local_VAT_incl: {self.cost_local_VAT_incl}
|
||||
currency_cost: {self.currency_cost}
|
||||
latency_manufacture: {self.latency_manufacture}
|
||||
id_unit_measurement_quantity: {self.id_unit_measurement_quantity}
|
||||
symbol_unit_measurement_quantity: {self.symbol_unit_measurement_quantity}
|
||||
symbol_is_suffix_not_prefix_unit_measurement_quantity: {self.symbol_is_suffix_not_prefix_unit_measurement_quantity}
|
||||
name_singular_unit_measurement_quantity: {self.name_singular_unit_measurement_quantity}
|
||||
name_plural_unit_measurement_quantity: {self.name_plural_unit_measurement_quantity}
|
||||
count_unit_measurement_per_quantity_step: {self.count_unit_measurement_per_quantity_step}
|
||||
quantity_min: {self.quantity_min}
|
||||
quantity_max: {self.quantity_max}
|
||||
quantity_stock: {self.quantity_stock}
|
||||
is_subscription: {self.is_subscription}
|
||||
id_unit_measurement_interval_recurrence: {self.id_unit_measurement_interval_recurrence}
|
||||
symbol_unit_measurement_interval_recurrence: {self.symbol_unit_measurement_interval_recurrence}
|
||||
symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence: {self.symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence}
|
||||
name_singular_unit_measurement_interval_recurrence: {self.name_singular_unit_measurement_interval_recurrence}
|
||||
name_plural_unit_measurement_interval_recurrence: {self.name_plural_unit_measurement_interval_recurrence}
|
||||
count_interval_recurrence: {self.count_interval_recurrence}
|
||||
id_stripe_product: {self.id_stripe_product}
|
||||
does_expire_faster_once_unsealed: {self.does_expire_faster_once_unsealed}
|
||||
id_unit_measurement_interval_expiration_unsealed: {self.id_unit_measurement_interval_expiration_unsealed}
|
||||
symbol_unit_measurement_interval_expiration_unsealed: {self.symbol_unit_measurement_interval_expiration_unsealed}
|
||||
symbol_is_suffix_not_prefix_unit_interval_expiration_unsealed: {self.symbol_is_suffix_not_prefix_unit_interval_expiration_unsealed}
|
||||
name_singular_unit_measurement_interval_expiration_unsealed: {self.name_singular_unit_measurement_interval_expiration_unsealed}
|
||||
name_plural_unit_measurement_interval_expiration_unsealed: {self.name_plural_unit_measurement_interval_expiration_unsealed}
|
||||
count_interval_expiration_unsealed: {self.count_interval_expiration_unsealed}
|
||||
has_variations: {self.has_variations}
|
||||
csv_id_pairs_variation: {self.csv_id_pairs_variation}
|
||||
can_view: {self.can_view}
|
||||
can_edit: {self.can_edit}
|
||||
can_admin: {self.can_admin}
|
||||
variation tree: {self.variation_tree}
|
||||
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_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]
|
||||
raise ValueError(f"{av.error_msg_str(variation, 'variation', _m, Product_Variation)}\nProduct_Variation already in product.")
|
||||
except KeyError:
|
||||
self.variation_index[variation.id_variation] = len(self.variations)
|
||||
self.variations.append(variation)
|
||||
""
|
||||
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_variation_type(self, variation_type):
|
||||
_m = 'Product_Permutation.add_product_variation_type'
|
||||
if self.variation_tree is None:
|
||||
self.variation_tree = Product_Variation_Tree.from_product_variation_type(variation_type)
|
||||
else:
|
||||
self.variation_tree.add_product_variation_type(variation_type)
|
||||
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]
|
||||
raise ValueError(f"{av.error_msg_str(price, 'price', _m, Product_Price)}\nPrice already in product.")
|
||||
except KeyError:
|
||||
self.price_index[price.display_order] = len(self.prices)
|
||||
self.prices.append(price)
|
||||
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]
|
||||
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_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]
|
||||
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_Permutation.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
|
||||
Product_Permutation.ATTR_ID_PRODUCT: self.id_product,
|
||||
Product_Permutation.ATTR_ID_PRODUCT_VARIATION: 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_UNIT_LOCAL_VAT_EXCL: f"<strong>{self.symbol_currency_cost}</strong>{self.cost_local_VAT_excl}"
|
||||
}
|
||||
Helper_App.console_log('permutation row: ', a)
|
||||
return a
|
||||
|
||||
|
||||
"""
|
||||
class Permutation_Product_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 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]
|
||||
link.id_product = query_row[1]
|
||||
link.id_category = query_row[2]
|
||||
link.id_variation = query_row[3]
|
||||
return link
|
||||
"""
|
||||
|
||||
class Product_Permutation_Temp(db.Model, Store_Base):
|
||||
__tablename__: ClassVar[str] = 'Shop_Product_Permutation_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_permutation: int = db.Column(db.Integer)
|
||||
id_product: int = db.Column(db.Integer)
|
||||
csv_id_pairs_variation: str = db.Column(db.String(4000))
|
||||
description: str = db.Column(db.String(4000))
|
||||
cost_local_VAT_excl: float = db.Column(db.Float)
|
||||
cost_local_VAT_incl: float = db.Column(db.Float)
|
||||
id_currency_cost: int = db.Column(db.Integer)
|
||||
profit_local_min: float = db.Column(db.Float)
|
||||
latency_manufacture: int = db.Column(db.Integer)
|
||||
id_unit_measurement_quantity: int = db.Column(db.Integer)
|
||||
count_unit_measurement_per_quantity_step: int = db.Column(db.Float)
|
||||
quantity_min: int = db.Column(db.Integer)
|
||||
quantity_max: int = db.Column(db.Integer)
|
||||
quantity_stock: int = db.Column(db.Integer)
|
||||
is_subscription: bool = db.Column(db.Boolean)
|
||||
id_unit_measurement_interval_recurrence: int = db.Column(db.Integer)
|
||||
count_interval_recurrence: int = db.Column(db.Float)
|
||||
id_stripe_product: str = db.Column(db.String(50))
|
||||
does_expire_faster_once_unsealed: bool = db.Column(db.Boolean)
|
||||
id_unit_measurement_interval_expiration_unsealed: int = db.Column(db.Integer)
|
||||
count_interval_expiration_unsealed: int = db.Column(db.Integer)
|
||||
active: bool = db.Column(db.Boolean)
|
||||
guid: str = db.Column(db.String(36))
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_product_permutation(cls, product_permutation):
|
||||
Helper_App.console_log(f'Product_Permutation_Temp.from_product_permutation: {product_permutation}\ntype(cost local): {str(type(product_permutation.cost_local_VAT_excl))}')
|
||||
row = cls()
|
||||
row.id_permutation = product_permutation.id_permutation
|
||||
row.id_product = product_permutation.id_product
|
||||
row.csv_id_pairs_variation = product_permutation.csv_id_pairs_variation
|
||||
row.description = product_permutation.description
|
||||
row.cost_local_VAT_excl = product_permutation.cost_local_VAT_excl if product_permutation.cost_local_VAT_excl != 'None' else None
|
||||
row.cost_local_VAT_incl = product_permutation.cost_local_VAT_incl if product_permutation.cost_local_VAT_incl != 'None' else None
|
||||
row.id_currency_cost = product_permutation.currency_cost.id_currency
|
||||
row.profit_local_min = product_permutation.profit_local_min if product_permutation.profit_local_min != 'None' else None
|
||||
row.latency_manufacture = product_permutation.latency_manufacture
|
||||
row.id_unit_measurement_quantity = product_permutation.id_unit_measurement_quantity
|
||||
row.count_unit_measurement_per_quantity_step = product_permutation.count_unit_measurement_per_quantity_step
|
||||
row.quantity_min = product_permutation.quantity_min
|
||||
row.quantity_max = product_permutation.quantity_max
|
||||
row.quantity_stock = product_permutation.quantity_stock
|
||||
row.is_subscription = product_permutation.is_subscription
|
||||
row.id_unit_measurement_interval_recurrence = product_permutation.id_unit_measurement_interval_recurrence
|
||||
row.count_interval_recurrence = product_permutation.count_interval_recurrence
|
||||
row.id_stripe_product = product_permutation.id_stripe_product
|
||||
row.does_expire_faster_once_unsealed = product_permutation.does_expire_faster_once_unsealed
|
||||
row.id_unit_measurement_interval_expiration_unsealed = product_permutation.id_unit_measurement_interval_expiration_unsealed
|
||||
row.count_interval_expiration_unsealed = product_permutation.count_interval_expiration_unsealed
|
||||
row.active = product_permutation.active
|
||||
return row
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id_permutation: {self.id_permutation}
|
||||
id_product: {self.id_product}
|
||||
csv_id_pairs_variation: {self.csv_id_pairs_variation}
|
||||
description: {self.description}
|
||||
cost_local_VAT_excl: {self.cost_local_VAT_excl}
|
||||
cost_local_VAT_incl: {self.cost_local_VAT_incl}
|
||||
id_currency_cost: {self.id_currency_cost}
|
||||
profit_local_min: {self.profit_local_min}
|
||||
latency_manufacture: {self.latency_manufacture}
|
||||
id_unit_measurement_quantity: {self.id_unit_measurement_quantity}
|
||||
{Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP}: {self.count_unit_measurement_per_quantity_step}
|
||||
quantity_min: {self.quantity_min}
|
||||
quantity_max: {self.quantity_max}
|
||||
quantity_stock: {self.quantity_stock}
|
||||
is_subscription: {self.is_subscription}
|
||||
id_unit_measurement_interval_recurrence: {self.id_unit_measurement_interval_recurrence}
|
||||
count_interval_recurrence: {self.count_interval_recurrence}
|
||||
id_stripe_product: {self.id_stripe_product}
|
||||
does_expire_faster_once_unsealed: {self.does_expire_faster_once_unsealed}
|
||||
id_unit_measurement_interval_expiration_unsealed: {self.id_unit_measurement_interval_expiration_unsealed}
|
||||
count_interval_expiration_unsealed: {self.count_interval_expiration_unsealed}
|
||||
active: {self.active}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
"""
|
||||
def to_json(self):
|
||||
return {
|
||||
self.ATTR_ID_PRODUCT_PERMUTATION: int(self.id_permutation),
|
||||
self.ATTR_ID_PRODUCT: int(self.id_product),
|
||||
self.FLAG_DESCRIPTION: self.description,
|
||||
Product_Permutation.FLAG_COST_LOCAL: float(self.cost_local),
|
||||
Product_Permutation.FLAG_CURRENCY_COST: int(self.id_currency_cost),
|
||||
Product_Permutation.FLAG_PROFIT_LOCAL_MIN: float(self.profit_local_min),
|
||||
Product_Permutation.FLAG_LATENCY_MANUFACTURE: int(self.latency_manufacture),
|
||||
Product_Permutation.FLAG_UNIT_MEASUREMENT_QUANTITY: int(self.id_unit_measurement_quantity),
|
||||
Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP: float(self.count_unit_measurement_per_quantity_step),
|
||||
self.FLAG_QUANTITY_MIN: float(self.quantity_min),
|
||||
self.FLAG_QUANTITY_MAX: float(self.quantity_max),
|
||||
Product_Permutation.FLAG_QUANTITY_STOCK: float(self.quantity_stock),
|
||||
Product_Permutation.FLAG_IS_SUBSCRIPTION: bool(self.is_subscription),
|
||||
Product_Permutation.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: int(self.id_unit_measurement_interval_recurrence) if self.id_unit_measurement_interval_recurrence != '' else None,
|
||||
Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: float(self.count_interval_recurrence) if self.count_interval_recurrence != '' else None,
|
||||
Product_Permutation.FLAG_ID_STRIPE_PRODUCT: self.id_stripe_product,
|
||||
Product_Permutation.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED: bool(self.does_expire_faster_once_unsealed),
|
||||
Product_Permutation.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: int(self.id_unit_measurement_interval_expiration_unsealed) if self.id_unit_measurement_interval_expiration_unsealed != '' else None,
|
||||
Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: float(self.count_interval_expiration_unsealed) if self.count_interval_expiration_unsealed != '' else None,
|
||||
self.FLAG_ACTIVE: bool(self.active),
|
||||
self.FLAG_GUID: self.guid
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Price Business Object
|
||||
|
||||
Description:
|
||||
Business object for product price
|
||||
"""
|
||||
|
||||
# internal
|
||||
from business_objects.currency import Currency
|
||||
from business_objects.region import Region
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
# external
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar
|
||||
|
||||
class Product_Price(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT_PRICE
|
||||
NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_TEXT
|
||||
|
||||
id_price = db.Column(db.Integer, primary_key=True)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
"""
|
||||
id_currency = db.Column(db.Integer)
|
||||
code_currency = db.Column(db.String(50))
|
||||
name_currency = db.Column(db.String(255))
|
||||
symbol_currency = db.Column(db.String(50))
|
||||
"""
|
||||
# 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)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
self.currency = None
|
||||
self.delivery_region = None
|
||||
@classmethod
|
||||
def from_DB_get_many_product_catalogue(cls, query_row):
|
||||
# _m = 'Product_Price.from_DB_get_many_product_catalogue'
|
||||
price = cls()
|
||||
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.currency = Currency.from_DB_get_many_product_price_and_discount_and_delivery_region(query_row)
|
||||
"""
|
||||
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'''Product_Price
|
||||
id: {self.id_price}
|
||||
id_permutation: {self.id_permutation}
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
currency: {self.currency}
|
||||
value_local (VAT incl): {self.value_local_VAT_incl}
|
||||
value_local (VAT excl): {self.value_local_VAT_excl}
|
||||
display_order (UID): {self.display_order}
|
||||
{self.FLAG_TEXT}: {self.currency.symbol} {self.value_local_VAT_incl}
|
||||
'''
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_PRODUCT_PRICE: self.id_price,
|
||||
self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation,
|
||||
self.ATTR_ID_PRODUCT: self.id_product,
|
||||
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
|
||||
self.FLAG_CURRENCY: self.currency.to_json(),
|
||||
# Region.ATTR_ID_REGION_DELIVERY: self.id_region,
|
||||
self.FLAG_VALUE_LOCAL_VAT_INCL: self.value_local_VAT_incl,
|
||||
self.FLAG_VALUE_LOCAL_VAT_EXCL: self.value_local_VAT_excl,
|
||||
self.FLAG_DISPLAY_ORDER: self.display_order
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
price = cls()
|
||||
price.id_price = json[cls.ATTR_ID_PRODUCT_PRICE]
|
||||
price.id_permutation = json[cls.ATTR_ID_PRODUCT_PERMUTATION]
|
||||
price.id_product = json[cls.ATTR_ID_PRODUCT]
|
||||
price.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
|
||||
price.currency = Currency.from_json(json)
|
||||
# price.id_region = json[Region.ATTR_ID_REGION_DELIVERY]
|
||||
price.value_local_VAT_incl = json[cls.FLAG_VALUE_LOCAL_VAT_INCL]
|
||||
price.value_local_VAT_excl = json[cls.FLAG_VALUE_LOCAL_VAT_EXCL]
|
||||
price.display_order = json[cls.FLAG_DISPLAY_ORDER]
|
||||
return price
|
||||
@@ -1,217 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Product_Variation Business Object
|
||||
|
||||
Description:
|
||||
Business object for product variation
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.db_base import Get_Many_Parameters_Base
|
||||
from business_objects.store.store_base import Store_Base
|
||||
# from business_objects.store.product_variation_type import Product_Variation_Type
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar
|
||||
from pydantic import BaseModel
|
||||
from itertools import filterfalse
|
||||
from operator import attrgetter
|
||||
|
||||
|
||||
class Product_Variation(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT_VARIATION
|
||||
NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME
|
||||
|
||||
id_variation = db.Column(db.Integer, primary_key=True)
|
||||
id_type = db.Column(db.Integer)
|
||||
code = db.Column(db.String(50))
|
||||
name = db.Column(db.String(255))
|
||||
display_order = db.Column(db.Integer)
|
||||
active = db.Column(db.Boolean)
|
||||
|
||||
id_permutation = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.variation_type = None
|
||||
|
||||
@classmethod
|
||||
def from_DB_get_many_product_catalogue(cls, query_row):
|
||||
variation = Product_Variation.from_DB_get_many_product_variation(query_row)
|
||||
variation.id_product = query_row[11]
|
||||
variation.id_permutation = query_row[12]
|
||||
variation.id_category = query_row[13]
|
||||
# variation.variation_type = Product_Variation_Type.from_DB_get_many_product_catalogue(query_row)
|
||||
return variation
|
||||
|
||||
@classmethod
|
||||
def from_DB_get_many_product_variation(cls, query_row):
|
||||
variation = cls()
|
||||
variation.id_variation = query_row[0]
|
||||
variation.id_type = query_row[1]
|
||||
variation.code = query_row[2]
|
||||
variation.name = query_row[3]
|
||||
variation.display_order = query_row[4]
|
||||
variation.active = av.input_bool(query_row[5], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_get_many_product_variation')
|
||||
return variation
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
variation = cls()
|
||||
variation.id_variation = json[cls.ATTR_ID_PRODUCT_VARIATION]
|
||||
variation.id_type = json[cls.ATTR_ID_PRODUCT_VARIATION_TYPE]
|
||||
variation.code = json[cls.FLAG_CODE]
|
||||
variation.name = json[cls.FLAG_NAME]
|
||||
variation.display_order = json[cls.FLAG_DISPLAY_ORDER]
|
||||
variation.active = 1 if av.input_bool(json[cls.FLAG_ACTIVE], cls.FLAG_ACTIVE, f'{cls.__name__}.from_json') else 0
|
||||
variation.id_permutation = json.get(cls.ATTR_ID_PRODUCT_PERMUTATION, None)
|
||||
variation.id_product = json.get(cls.ATTR_ID_PRODUCT, None)
|
||||
variation.id_category = json.get(cls.ATTR_ID_PRODUCT_CATEGORY, None)
|
||||
return variation
|
||||
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.__class__.__name__}
|
||||
id_variation: {self.id_variation}
|
||||
id_type: {self.id_type}
|
||||
code: {self.code}
|
||||
name: {self.name}
|
||||
display_order: {self.display_order}
|
||||
active: {self.active}
|
||||
id_permutation: {self.id_permutation}
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
variation_type: {self.variation_type}
|
||||
'''
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_PRODUCT_VARIATION: self.id_variation,
|
||||
self.ATTR_ID_PRODUCT_VARIATION_TYPE: self.id_type,
|
||||
self.FLAG_CODE: self.code,
|
||||
self.FLAG_NAME: self.name,
|
||||
self.FLAG_DISPLAY_ORDER: self.display_order,
|
||||
self.FLAG_ACTIVE: self.active,
|
||||
self.ATTR_ID_PRODUCT: self.id_product,
|
||||
self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation,
|
||||
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
|
||||
}
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_variation,
|
||||
'text': self.name
|
||||
}
|
||||
|
||||
class Parameters_Product_Variation(Get_Many_Parameters_Base):
|
||||
a_get_all_variation_type: bool
|
||||
a_get_inactive_variation_type: bool
|
||||
a_ids_variation_type: str
|
||||
a_get_all_variation: bool
|
||||
a_get_inactive_variation: bool
|
||||
a_ids_variation: str
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
return cls(
|
||||
a_get_all_variation_type = True,
|
||||
a_get_inactive_variation_type = False,
|
||||
a_ids_variation_type = '',
|
||||
a_get_all_variation = True,
|
||||
a_get_inactive_variation = False,
|
||||
a_ids_variation = ''
|
||||
)
|
||||
@classmethod
|
||||
def from_filters_product_variation(cls, form):
|
||||
parameters = cls.get_default()
|
||||
get_inactive = not form.active.data
|
||||
parameters.a_get_inactive_variation_type = get_inactive
|
||||
parameters.a_get_inactive_variation = get_inactive
|
||||
return parameters
|
||||
|
||||
"""
|
||||
class Product_Variation_Container(BaseModel):
|
||||
variation_types: list = []
|
||||
variations: list = []
|
||||
|
||||
def add_product_variation_type(self, variation_type):
|
||||
av.val_instance(variation_type, 'variation_type', 'Product_Variation_Container.add_product_variation_type', Product_Variation_Type)
|
||||
self.variations.append(variation_type)
|
||||
def add_product_variation(self, variation):
|
||||
av.val_instance(variation, 'variation', 'Product_Variation_Container.add_product_variation', Product_Variation)
|
||||
if variation.variation_type is None:
|
||||
variation_type = next(filterfalse(lambda x: x.id_type != variation.id_type, self.variation_types), None)
|
||||
if variation_type is not None:
|
||||
variation.variation_type = variation_type
|
||||
self.variations.append(variation)
|
||||
|
||||
def __repr__(self):
|
||||
return f'Product_Variation_Container:\nvariations_types: {self.variation_types}\nvariations: {self.variations}'
|
||||
|
||||
def to_list_variation_options(self):
|
||||
list_variations = []
|
||||
for variation in self.variations:
|
||||
list_variations.append(variation.to_json_option())
|
||||
Helper_App.console_log(f'list_variations: {list_variations}')
|
||||
return list_variations
|
||||
def to_list_variation_type_options(self):
|
||||
list_variation_types = []
|
||||
for variation_type in self.variation_types:
|
||||
list_variation_types.append(variation_type.to_json_option())
|
||||
return list_variation_types
|
||||
"""
|
||||
|
||||
class Product_Variation_Temp(db.Model, Store_Base):
|
||||
__tablename__ = 'Shop_Variation_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_variation: int = db.Column(db.Integer) # , primary_key=True)
|
||||
id_type: int = db.Column(db.Integer, nullable=False)
|
||||
code: str = db.Column(db.String(50))
|
||||
name: str = db.Column(db.String(255))
|
||||
active: bool = db.Column(db.Boolean)
|
||||
display_order: int = db.Column(db.Integer)
|
||||
guid: str = db.Column(db.String(36))
|
||||
|
||||
def __repr__(self):
|
||||
attrs = '\n'.join(f'{k}={v!r}' for k, v in self.__dict__.items())
|
||||
return f'<{self.__class__.__name__}(\n{attrs}\n)>'
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_product_variation(cls, product_variation):
|
||||
row = cls()
|
||||
row.id_variation = product_variation.id_variation
|
||||
row.id_type = product_variation.id_type
|
||||
row.code = product_variation.code
|
||||
row.name = product_variation.name
|
||||
row.active = 1 if av.input_bool(product_variation.active, cls.FLAG_ACTIVE, f'{cls.__name__}.to_json') else 0
|
||||
row.display_order = product_variation.display_order
|
||||
return row
|
||||
def to_json(self):
|
||||
return {
|
||||
'id_variation': self.id_variation,
|
||||
'id_type': self.id_type,
|
||||
'code': self.code,
|
||||
'name': self.name,
|
||||
'active': self.active,
|
||||
'display_order': self.display_order,
|
||||
'guid': self.guid,
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
# internal
|
||||
from business_objects.store.product_variation import Product_Variation
|
||||
from business_objects.store.product_variation_type import Product_Variation_Type
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
|
||||
|
||||
class Product_Variation_Tree_Node():
|
||||
variation_type: Product_Variation_Type
|
||||
node_parent: None
|
||||
nodes_child: list
|
||||
def __init__(self):
|
||||
self.nodes_child = []
|
||||
def from_variation_type_and_node_parent(variation_type, node_parent):
|
||||
node = Product_Variation_Tree_Node()
|
||||
node.variation_type = variation_type
|
||||
node.node_parent = node_parent
|
||||
return node
|
||||
def from_node_parent(node_parent):
|
||||
node = Product_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 Product_Variation_Tree():
|
||||
node_root: Product_Variation_Tree_Node
|
||||
@classmethod
|
||||
def from_node_root(cls, node_root):
|
||||
tree = cls()
|
||||
tree.node_root = node_root
|
||||
return tree
|
||||
@classmethod
|
||||
def from_variation_type_root(cls, variation_type_root):
|
||||
node_root = Product_Variation_Tree_Node.from_variation_type_and_node_parent(variation_type_root, None)
|
||||
return cls.from_node_root(node_root)
|
||||
def is_equal(self, tree):
|
||||
my_type_list = self.get_product_variation_types()
|
||||
sz_me = len(my_type_list)
|
||||
other_type_list = tree.get_product_variation_types()
|
||||
sz_other = len(other_type_list)
|
||||
is_equal = (sz_me == sz_other)
|
||||
if is_equal:
|
||||
for index_type in range(sz_me):
|
||||
my_variation_type = my_type_list[index_type]
|
||||
other_variation_type = other_type_list[index_type]
|
||||
if my_variation_type.id_type != other_variation_type.id_type:
|
||||
is_equal = False
|
||||
break
|
||||
my_variation = my_variation_type.variations[0]
|
||||
other_variation = other_variation_type.variations[0]
|
||||
if my_variation.id_variation != other_variation.id_variation:
|
||||
is_equal = False
|
||||
break
|
||||
return is_equal
|
||||
@classmethod
|
||||
def from_product_permutation(cls, product_permutation):
|
||||
depth_max = len(product_permutation.variation_types)
|
||||
node_root = Product_Variation_Tree_Node.from_variation_type_and_node_parent(product_permutation.variation_types[0], None)
|
||||
node = node_root
|
||||
for depth in range(depth_max - 1):
|
||||
node = Product_Variation_Tree_Node.from_variation_type_and_node_parent(product_permutation.variation_types[depth + 1], node)
|
||||
return cls.from_node_root(node_root)
|
||||
@classmethod
|
||||
def from_product_variation_type(cls, product_variation_type):
|
||||
node_root = Product_Variation_Tree_Node.from_variation_type_and_node_parent(product_variation_type, None)
|
||||
return cls.from_node_root(node_root)
|
||||
@classmethod
|
||||
def from_product_variation_types(cls, product_variation_types):
|
||||
node_root = Product_Variation_Tree_Node.from_variation_type_and_node_parent(product_variation_types[0], None)
|
||||
tree = cls.from_node_root(node_root)
|
||||
if len(product_variation_types) > 1:
|
||||
for variation_type in product_variation_types[1:]:
|
||||
tree.add_product_variation_type(variation_type)
|
||||
return tree
|
||||
@classmethod
|
||||
def from_json_str(cls, json_str):
|
||||
variation_types = []
|
||||
if json_str is None or json_str == '': return None
|
||||
for json_variation_type in json_str.split(','):
|
||||
parts = json_variation_type.split(':')
|
||||
if len(parts) != 2: continue
|
||||
variation_type = Product_Variation_Type()
|
||||
variation_type.id_type = parts[0]
|
||||
variation = Product_Variation()
|
||||
variation_type.id_variation = parts[1]
|
||||
variation_type.variations = [variation]
|
||||
variation_types.append(variation_type)
|
||||
return cls.from_product_variation_types(variation_types)
|
||||
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_type(self, variation_type):
|
||||
node_leaf = self.get_node_leaf()
|
||||
node_new = Product_Variation_Tree_Node.from_variation_type_and_node_parent(variation_type, 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_type)
|
||||
node = node.nodes_child[0]
|
||||
at_leaf_node = node.is_leaf()
|
||||
types.append(node.variation_type)
|
||||
return types
|
||||
"""
|
||||
def get_product_variations(self):
|
||||
variations = []
|
||||
node = self.node_root
|
||||
at_leaf_node = node.is_leaf()
|
||||
variations.append(node.variation)
|
||||
while not at_leaf_node:
|
||||
node = node.nodes_child[0]
|
||||
at_leaf_node = node.is_leaf()
|
||||
variations.append(node.variation)
|
||||
return variations
|
||||
"""
|
||||
def to_preview_str(self):
|
||||
Helper_App.console_log(f'Product_Variation_Tree.to_preview_str')
|
||||
variation_types = self.get_product_variation_types()
|
||||
Helper_App.console_log(f'variation_types: {variation_types}')
|
||||
preview_str = ''
|
||||
for variation_type in variation_types:
|
||||
is_first = (preview_str == '')
|
||||
preview_str += f'{variation_type.name_singular}: {variation_type.variations[0].name}'
|
||||
if is_first:
|
||||
preview_str += '\n'
|
||||
Helper_App.console_log(f'preview_str: {preview_str}')
|
||||
return preview_str
|
||||
def to_json(self):
|
||||
variation_types = self.get_product_variation_types()
|
||||
json_variation_types = []
|
||||
for variation_type in variation_types:
|
||||
json_variation_types.append(variation_type.to_json())
|
||||
return json_variation_types
|
||||
def to_variation_id_pairs_str(self):
|
||||
variation_types = self.get_product_variation_types()
|
||||
pairs_str = ''
|
||||
for variation_type in variation_types:
|
||||
pairs_str += f'{variation_type.id_type}:{variation_type.variations[0].id_variation},'
|
||||
return pairs_str
|
||||
@@ -1,169 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Product Product_Variation Business Object
|
||||
|
||||
Description:
|
||||
Business object for product variation
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# VARIABLE INSTANTIATION
|
||||
# CLASSES
|
||||
# METHODS
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.store.product_variation import Product_Variation
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
# external
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar
|
||||
from pydantic import BaseModel
|
||||
from itertools import filterfalse
|
||||
from operator import attrgetter
|
||||
|
||||
class Product_Variation_Type(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT_VARIATION_TYPE
|
||||
NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME
|
||||
|
||||
id_type = db.Column(db.Integer, primary_key=True)
|
||||
code = db.Column(db.String(50))
|
||||
name_singular = db.Column(db.String(255))
|
||||
name_plural = db.Column(db.String(255))
|
||||
display_order = db.Column(db.Integer)
|
||||
active = db.Column(db.Boolean)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.variations = []
|
||||
|
||||
@classmethod
|
||||
def from_DB_get_many_product_catalogue(cls, query_row):
|
||||
variation_type = cls()
|
||||
variation_type.id_type = query_row[1]
|
||||
variation_type.code = query_row[6]
|
||||
variation_type.name_singular = query_row[7]
|
||||
variation_type.name_plural = query_row[8]
|
||||
variation_type.display_order = query_row[9]
|
||||
variation_type.active = av.input_bool(query_row[10], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_get_many_product_catalogue')
|
||||
variation_type.variations = [Product_Variation.from_DB_get_many_product_catalogue(query_row)]
|
||||
return variation_type
|
||||
|
||||
@classmethod
|
||||
def from_DB_get_many_product_variation(cls, query_row):
|
||||
variation_type = cls()
|
||||
variation_type.id_type = query_row[0]
|
||||
variation_type.code = query_row[1]
|
||||
variation_type.name_singular = query_row[2]
|
||||
variation_type.name_plural = query_row[3]
|
||||
variation_type.display_order = query_row[4]
|
||||
variation_type.active = av.input_bool(query_row[5], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_get_many_product_variation')
|
||||
return variation_type
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
variation_type = cls()
|
||||
variation_type.id_type = json[cls.ATTR_ID_PRODUCT_VARIATION_TYPE]
|
||||
variation_type.code = json[cls.FLAG_CODE]
|
||||
variation_type.name_singular = json.get(cls.FLAG_NAME_SINGULAR, json.get(cls.FLAG_NAME, ''))
|
||||
variation_type.name_plural = json[cls.FLAG_NAME_PLURAL]
|
||||
variation_type.display_order = json[cls.FLAG_DISPLAY_ORDER]
|
||||
variation_type.active = json[cls.FLAG_ACTIVE]
|
||||
variations = json.get(cls.FLAG_PRODUCT_VARIATIONS, [])
|
||||
if variations is not None and len(variations) > 0:
|
||||
variation_type.variations = [Product_Variation.from_json(variation) for variation in variations]
|
||||
return variation_type
|
||||
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.__class__.__name__}
|
||||
id_type: {self.id_type}
|
||||
code: {self.code}
|
||||
name_singular: {self.name_singular}
|
||||
name_plural: {self.name_plural}
|
||||
display_order: {self.display_order}
|
||||
active: {self.active}
|
||||
'''
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_PRODUCT_VARIATION_TYPE: self.id_type,
|
||||
self.FLAG_CODE: self.code,
|
||||
self.FLAG_NAME: self.name_singular,
|
||||
self.FLAG_NAME_PLURAL: self.name_plural,
|
||||
self.FLAG_DISPLAY_ORDER: self.display_order,
|
||||
self.FLAG_ACTIVE: self.active,
|
||||
self.FLAG_PRODUCT_VARIATIONS: [variation.to_json() for variation in self.variations]
|
||||
}
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_type,
|
||||
'text': self.name_singular
|
||||
}
|
||||
"""
|
||||
def get_preview_variations(self):
|
||||
preview = ''
|
||||
if len(self.variations) > 0:
|
||||
# preview = '\n'.join([variation.name for variation in self.variations])
|
||||
preview = '<p>' + '</p><p>'.join([variation.name for variation in self.variations]) + '</p>'
|
||||
return preview
|
||||
def get_str_list_ids_variation(self):
|
||||
if self.variations is None or len(self.variations) == 0:
|
||||
return ''
|
||||
return ','.join([str(variation.id_variation) for variation in self.variations])
|
||||
"""
|
||||
|
||||
class Product_Variation_Type_Temp(db.Model, Store_Base):
|
||||
__tablename__ = 'Shop_Variation_Type_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_type: int = db.Column(db.Integer)
|
||||
code: str = db.Column(db.String(50))
|
||||
name: str = db.Column(db.String(255))
|
||||
name_plural: str = db.Column(db.String(256))
|
||||
active: bool = db.Column(db.Boolean)
|
||||
display_order: int = db.Column(db.Integer)
|
||||
guid: str = db.Column(db.String(36))
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_product_variation_type(cls, product_variation_type):
|
||||
row = cls()
|
||||
row.id_type = product_variation_type.id_type
|
||||
row.code = product_variation_type.code
|
||||
row.name = product_variation_type.name_singular
|
||||
row.name_plural = product_variation_type.name_plural
|
||||
row.active = 1 if av.input_bool(product_variation_type.active, cls.FLAG_ACTIVE, f'{cls.__name__}.from_product_variation_type') else 0
|
||||
row.display_order = product_variation_type.display_order
|
||||
return row
|
||||
def to_json(self):
|
||||
return {
|
||||
'id_type': self.id_type,
|
||||
'code': self.code,
|
||||
'name': self.name,
|
||||
'name_plural': self.name_plural,
|
||||
'active': self.active,
|
||||
'display_order': self.display_order,
|
||||
'guid': self.guid,
|
||||
}
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.__class__.__name__}
|
||||
id_temp: {self.id_temp}
|
||||
id_type: {self.id_type}
|
||||
code: {self.code}
|
||||
name: {self.name}
|
||||
name_plural: {self.name_plural}
|
||||
active: {self.active}
|
||||
display_order: {self.display_order}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
@@ -1,303 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Stock Item Business Object
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms.store.stock_item import Filters_Stock_Item
|
||||
from business_objects.db_base import Get_Many_Parameters_Base
|
||||
from business_objects.currency import Currency
|
||||
# from business_objects.discount import Discount
|
||||
from business_objects.store.product_variation_tree import Product_Variation_Tree
|
||||
from business_objects.store.storage_location import Storage_Location
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar, Optional
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class Stock_Item(db.Model, Store_Base):
|
||||
ATTR_ID_CURRENCY_COST: ClassVar[str] = f'{Store_Base.ATTR_ID_CURRENCY}_cost'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_CURRENCY
|
||||
NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME
|
||||
FLAG_DATE_CONSUMED: ClassVar[str] = 'date_consumed'
|
||||
FLAG_DATE_EXPIRATION: ClassVar[str] = 'date_expiration'
|
||||
FLAG_DATE_PURCHASED: ClassVar[str] = 'date_purchased'
|
||||
FLAG_DATE_RECEIVED: ClassVar[str] = 'date_received'
|
||||
FLAG_DATE_UNSEALED: ClassVar[str] = 'date_unsealed'
|
||||
FLAG_IS_CONSUMED: ClassVar[str] = 'is_consumed'
|
||||
FLAG_IS_SEALED: ClassVar[str] = 'is_sealed'
|
||||
|
||||
id_stock = db.Column(db.Integer, primary_key=True)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
id_location_storage = db.Column(db.Integer)
|
||||
id_plant = db.Column(db.Integer)
|
||||
id_region = db.Column(db.Integer)
|
||||
id_currency_cost = db.Column(db.Integer)
|
||||
cost_local_VAT_excl = db.Column(db.Float)
|
||||
cost_local_VAT_incl = db.Column(db.Float)
|
||||
date_purchased = db.Column(db.DateTime)
|
||||
date_received = db.Column(db.DateTime)
|
||||
is_sealed = db.Column(db.Boolean)
|
||||
date_unsealed = db.Column(db.DateTime)
|
||||
date_expiration = db.Column(db.DateTime)
|
||||
is_consumed = db.Column(db.Boolean)
|
||||
date_consumed = db.Column(db.DateTime)
|
||||
active = db.Column(db.Boolean)
|
||||
"""
|
||||
can_view = db.Column(db.Boolean)
|
||||
can_edit = db.Column(db.Boolean)
|
||||
can_admin = db.Column(db.Boolean)
|
||||
"""
|
||||
# variation_tree: Product_Variation_Tree = None
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
self.currency_cost = None
|
||||
self.storage_location = None
|
||||
self.variation_tree = None
|
||||
self.has_variations = False
|
||||
|
||||
def from_DB_stock_item(query_row):
|
||||
_m = 'Product.from_DB_stock_item'
|
||||
v_arg_type = 'class attribute'
|
||||
stock_item = Stock_Item()
|
||||
stock_item.id_stock = query_row[0]
|
||||
stock_item.id_permutation = query_row[1]
|
||||
stock_item.id_product = query_row[2]
|
||||
stock_item.id_category = query_row[3]
|
||||
stock_item.id_location_storage = query_row[4]
|
||||
stock_item.storage_location = Storage_Location.from_DB_stock_item(query_row)
|
||||
stock_item.id_currency_cost = query_row[12]
|
||||
stock_item.currency_cost = Currency.from_DB_stock_item(query_row)
|
||||
stock_item.cost_local_VAT_excl = query_row[15]
|
||||
stock_item.cost_local_VAT_incl = query_row[16]
|
||||
stock_item.date_purchased = query_row[17]
|
||||
stock_item.date_received = query_row[18]
|
||||
stock_item.is_sealed = av.input_bool(query_row[19], "is_sealed", _m, v_arg_type=v_arg_type)
|
||||
stock_item.date_unsealed = query_row[20]
|
||||
stock_item.date_expiration = query_row[21]
|
||||
stock_item.is_consumed = av.input_bool(query_row[22], "is_consumed", _m, v_arg_type=v_arg_type)
|
||||
stock_item.date_consumed = query_row[23]
|
||||
stock_item.active = av.input_bool(query_row[24], "active", _m, v_arg_type=v_arg_type)
|
||||
"""
|
||||
stock_item.can_view = av.input_bool(query_row[24], "can_view", _m, v_arg_type=v_arg_type)
|
||||
stock_item.can_edit = av.input_bool(query_row[25], "can_edit", _m, v_arg_type=v_arg_type)
|
||||
stock_item.can_admin = av.input_bool(query_row[26], "can_admin", _m, v_arg_type=v_arg_type)
|
||||
"""
|
||||
return stock_item
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
stock_item = cls()
|
||||
stock_item.id_stock = json[cls.ATTR_ID_STOCK_ITEM]
|
||||
stock_item.id_permutation = json.get(cls.ATTR_ID_PRODUCT_PERMUTATION, 0)
|
||||
stock_item.id_product = json[cls.ATTR_ID_PRODUCT]
|
||||
stock_item.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
|
||||
Helper_App.console_log(f'json: {json}\nhalf stock item: {stock_item}')
|
||||
stock_item.variation_tree = Product_Variation_Tree.from_json_str(json[cls.FLAG_PRODUCT_VARIATIONS])
|
||||
stock_item.date_purchased = json[cls.FLAG_DATE_PURCHASED]
|
||||
stock_item.date_received = json[cls.FLAG_DATE_RECEIVED]
|
||||
stock_item.id_location_storage = json[cls.ATTR_ID_STORAGE_LOCATION]
|
||||
stock_item.id_currency_cost = json[cls.ATTR_ID_CURRENCY_COST]
|
||||
stock_item.cost_local_VAT_excl = json[cls.FLAG_COST_UNIT_LOCAL_VAT_EXCL]
|
||||
stock_item.cost_local_VAT_incl = json[cls.FLAG_COST_UNIT_LOCAL_VAT_INCL]
|
||||
stock_item.is_sealed = json[cls.FLAG_IS_SEALED]
|
||||
stock_item.date_unsealed = json[cls.FLAG_DATE_UNSEALED]
|
||||
stock_item.date_expiration = json[cls.FLAG_DATE_EXPIRATION]
|
||||
stock_item.is_consumed = json[cls.FLAG_IS_CONSUMED]
|
||||
stock_item.date_consumed = json[cls.FLAG_DATE_CONSUMED]
|
||||
stock_item.active = json[cls.FLAG_ACTIVE]
|
||||
return stock_item
|
||||
def __repr__(self):
|
||||
return f'''Stock Item
|
||||
id_stock: {self.id_stock}
|
||||
id_permutation: {self.id_permutation}
|
||||
id_product: {self.id_product}
|
||||
id_category: {self.id_category}
|
||||
variations: {self.variation_tree.to_preview_str() if self.variation_tree is not None else 'None'}
|
||||
storage_location: {self.storage_location}
|
||||
currency: {self.currency_cost}
|
||||
cost_local_VAT_excl: {self.cost_local_VAT_excl}
|
||||
cost_local_VAT_incl: {self.cost_local_VAT_incl}
|
||||
date_purchased: {self.date_purchased}
|
||||
date_received: {self.date_received}
|
||||
is_sealed: {self.is_sealed}
|
||||
date_unsealed: {self.date_unsealed}
|
||||
date_expiration: {self.date_expiration}
|
||||
is_consumed: {self.is_consumed}
|
||||
date_consumed: {self.date_consumed}
|
||||
active: {self.active}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_STOCK_ITEM: self.id_stock,
|
||||
self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation,
|
||||
self.ATTR_ID_PRODUCT: self.id_product,
|
||||
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
|
||||
self.FLAG_STORAGE_LOCATION: self.storage_location.to_json(),
|
||||
self.FLAG_CURRENCY_COST: self.currency_cost.to_json(),
|
||||
self.FLAG_COST_UNIT_LOCAL_VAT_EXCL: self.cost_local_VAT_excl,
|
||||
self.FLAG_COST_UNIT_LOCAL_VAT_INCL: self.cost_local_VAT_incl,
|
||||
}
|
||||
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_permutation_row_list(self):
|
||||
list_rows = []
|
||||
for permutation in self.permutations:
|
||||
list_rows.append(permutation.to_row_permutation())
|
||||
return list_rows
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_stock_item,
|
||||
'text': self.id_stock_item
|
||||
}
|
||||
"""
|
||||
|
||||
class Parameters_Stock_Item(Get_Many_Parameters_Base):
|
||||
a_get_all_product_permutation: bool
|
||||
a_get_inactive_product_permutation: bool
|
||||
a_ids_product_permutation: str
|
||||
a_get_all_stock_item: bool
|
||||
a_get_inactive_stock_item: bool
|
||||
a_ids_stock_item: str
|
||||
a_get_all_region_storage: bool
|
||||
a_get_inactive_region_storage: bool
|
||||
a_ids_region_storage: str
|
||||
a_get_all_plant_storage: bool
|
||||
a_get_inactive_plant_storage: bool
|
||||
a_ids_plant_storage: str
|
||||
a_get_all_location_storage: bool
|
||||
a_get_inactive_location_storage: bool
|
||||
a_ids_location_storage: str
|
||||
a_date_received_to: Optional[datetime] = None
|
||||
a_get_sealed_stock_item_only: bool
|
||||
a_get_unsealed_stock_item_only: bool
|
||||
a_get_expired_stock_item_only: bool
|
||||
a_get_nonexpired_stock_item_only: bool
|
||||
a_get_consumed_stock_item_only: bool
|
||||
a_get_nonconsumed_stock_item_only: bool
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
return cls(
|
||||
# a_id_user = id_user,
|
||||
a_get_all_product_permutation = False,
|
||||
a_get_inactive_product_permutation = False,
|
||||
a_ids_product_permutation = '',
|
||||
a_get_all_stock_item = True,
|
||||
a_get_inactive_stock_item = False,
|
||||
a_ids_stock_item = '',
|
||||
a_get_all_region_storage = True,
|
||||
a_get_inactive_region_storage = False,
|
||||
a_ids_region_storage = '',
|
||||
a_get_all_plant_storage = True,
|
||||
a_get_inactive_plant_storage = False,
|
||||
a_ids_plant_storage = '',
|
||||
a_get_all_location_storage = True,
|
||||
a_get_inactive_location_storage = False,
|
||||
a_ids_location_storage = '',
|
||||
a_date_received_to = None,
|
||||
a_get_sealed_stock_item_only = False,
|
||||
a_get_unsealed_stock_item_only = False,
|
||||
a_get_expired_stock_item_only = False,
|
||||
a_get_nonexpired_stock_item_only = False,
|
||||
a_get_consumed_stock_item_only = False,
|
||||
a_get_nonconsumed_stock_item_only = False
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_form_stock_item(cls, form):
|
||||
return cls.get_default()
|
||||
|
||||
|
||||
class Stock_Item_Temp(db.Model, Store_Base):
|
||||
__tablename__: ClassVar[str] = 'Shop_Stock_Item_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_stock: int = db.Column(db.Integer, primary_key=True)
|
||||
# id_category: int = db.Column(db.Integer)
|
||||
id_product: int = db.Column(db.Integer)
|
||||
# has_variations: bool = db.Column(db.Boolean)
|
||||
id_permutation: int = db.Column(db.Integer)
|
||||
id_pairs_variations: str = db.Column(db.String(4000))
|
||||
date_purchased: datetime = db.Column(db.DateTime)
|
||||
date_received: datetime = db.Column(db.DateTime, nullable=True)
|
||||
id_location_storage: int = db.Column(db.Integer)
|
||||
id_currency_cost: int = db.Column(db.Integer)
|
||||
cost_local_VAT_excl: float = db.Column(db.Float)
|
||||
cost_local_VAT_incl: float = db.Column(db.Float)
|
||||
is_sealed: bool = db.Column(db.Boolean)
|
||||
date_unsealed: datetime = db.Column(db.DateTime, nullable=True)
|
||||
date_expiration: datetime = db.Column(db.DateTime, nullable=True)
|
||||
is_consumed: bool = db.Column(db.Boolean)
|
||||
date_consumed: datetime = db.Column(db.DateTime, nullable=True)
|
||||
active: bool = db.Column(db.Boolean)
|
||||
guid: str = db.Column(db.String(36))
|
||||
|
||||
@classmethod
|
||||
def from_stock_item(cls, stock_item):
|
||||
row = cls()
|
||||
row.id_stock = stock_item.id_stock
|
||||
# row.id_category = stock_item.id_category
|
||||
row.id_product = stock_item.id_product
|
||||
row.id_permutation = stock_item.id_permutation
|
||||
# row.has_variations = stock_item.has_variations
|
||||
row.id_pairs_variations = stock_item.variation_tree.to_json_str() if stock_item.variation_tree is not None else ''
|
||||
row.date_purchased = stock_item.date_purchased
|
||||
row.date_received = stock_item.date_received if stock_item.date_received else None
|
||||
row.id_location_storage = stock_item.id_location_storage
|
||||
row.id_currency_cost = stock_item.id_currency_cost
|
||||
row.cost_local_VAT_excl = stock_item.cost_local_VAT_excl
|
||||
row.cost_local_VAT_incl = stock_item.cost_local_VAT_incl
|
||||
row.is_sealed = 1 if stock_item.is_sealed else 0
|
||||
row.date_unsealed = stock_item.date_unsealed if stock_item.date_unsealed else None
|
||||
row.date_expiration = stock_item.date_expiration if stock_item.date_expiration else None
|
||||
row.is_consumed = 1 if stock_item.is_consumed else 0
|
||||
row.date_consumed = stock_item.date_consumed if stock_item.date_consumed else None
|
||||
row.active = 1 if stock_item.active else 0
|
||||
return row
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id_stock: {self.id_stock}
|
||||
id_product: {self.id_product}
|
||||
id_permutation: {self.id_permutation}
|
||||
id_pairs_variations: {self.id_pairs_variations}
|
||||
date_purchased: {self.date_purchased}
|
||||
date_received: {self.date_received}
|
||||
id_location_storage: {self.id_location_storage}
|
||||
id_currency_cost: {self.id_currency_cost}
|
||||
cost_local_VAT_excl: {self.cost_local_VAT_excl}
|
||||
cost_local_VAT_incl: {self.cost_local_VAT_incl}
|
||||
is_sealed: {self.is_sealed}
|
||||
date_unsealed: {self.date_unsealed}
|
||||
date_expiration: {self.date_expiration}
|
||||
is_consumed: {self.is_consumed}
|
||||
date_consumed: {self.date_consumed}
|
||||
active: {self.active}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
@@ -1,88 +0,0 @@
|
||||
"""
|
||||
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.plant import Plant
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from typing import ClassVar
|
||||
|
||||
|
||||
class Storage_Location(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_STORAGE_LOCATION
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
|
||||
__tablename__ = 'Shop_Storage_Location_Temp'
|
||||
id_location = db.Column(db.Integer, primary_key=True)
|
||||
id_plant = db.Column(db.Integer)
|
||||
code = db.Column(db.String(50))
|
||||
name = db.Column(db.String(255))
|
||||
active = db.Column(db.Boolean)
|
||||
|
||||
# plant = None
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
self.plant = None
|
||||
|
||||
@classmethod
|
||||
def from_DB_storage_location(cls, query_row):
|
||||
location = cls()
|
||||
location.id_location = query_row[0]
|
||||
location.id_plant = query_row[1]
|
||||
location.plant = Plant.from_DB_storage_location(query_row)
|
||||
location.code = query_row[4]
|
||||
location.name = query_row[5]
|
||||
location.active = query_row[6]
|
||||
return location
|
||||
@classmethod
|
||||
def from_DB_stock_item(cls, query_row):
|
||||
location = cls()
|
||||
location.id_location = query_row[4]
|
||||
location.id_plant = query_row[5]
|
||||
location.code = query_row[8]
|
||||
location.name = query_row[9]
|
||||
location.plant = Plant.from_DB_stock_item(query_row)
|
||||
return location
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.ATTR_ID_STORAGE_LOCATION}: {self.id_location}
|
||||
{self.ATTR_ID_PLANT}: {self.id_plant}
|
||||
{self.FLAG_CODE}: {self.code}
|
||||
{self.FLAG_NAME}: {self.name}
|
||||
{self.FLAG_ACTIVE}: {self.active}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_STORAGE_LOCATION: self.id_location,
|
||||
self.ATTR_ID_PLANT: self.id_plant,
|
||||
self.FLAG_CODE: self.code,
|
||||
self.FLAG_NAME: self.name,
|
||||
self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
|
||||
location = cls()
|
||||
location.id_location = json[cls.ATTR_ID_STORAGE_LOCATION],
|
||||
location.id_plant = json[cls.ATTR_ID_PLANT],
|
||||
location.code = json[cls.FLAG_CODE],
|
||||
location.name = json[cls.FLAG_NAME],
|
||||
location.active = json[cls.FLAG_ACTIVE]
|
||||
return location
|
||||
|
||||
def get_full_name(self):
|
||||
return f'{self.plant.name} - {self.name}'
|
||||
@@ -1,129 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Base Store Business Object
|
||||
|
||||
Description:
|
||||
Abstract business object for store objects
|
||||
"""
|
||||
|
||||
# internal
|
||||
# from helpers.DEPRECATED.helper_abc import Interface_ABC
|
||||
from business_objects.base import Base
|
||||
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(Base):
|
||||
# ATTR_ID_CURRENCY_COST: ClassVar[str] = 'id_currency_cost'
|
||||
ATTR_ID_CUSTOMER: ClassVar[str] = 'id_customer'
|
||||
ATTR_ID_CUSTOMER_ADDRESS: ClassVar[str] = 'id_address'
|
||||
ATTR_ID_CUSTOMER_SALES_ORDER: ClassVar[str] = 'id_customer_sales_order'
|
||||
ATTR_ID_DELIVERY_OPTION: ClassVar[str] = 'id_delivery_option'
|
||||
ATTR_ID_DISCOUNT: ClassVar[str] = 'id_discount'
|
||||
ATTR_ID_IMAGE: ClassVar[str] = 'id_image'
|
||||
ATTR_ID_MANUFACTURING_PURCHASE_ORDER: ClassVar[str] = 'id_order'
|
||||
ATTR_ID_MANUFACTURING_PURCHASE_ORDER_PRODUCT_LINK: ClassVar[str] = 'id_link'
|
||||
ATTR_ID_PLANT: ClassVar[str] = 'id_plant'
|
||||
ATTR_ID_PRODUCT: ClassVar[str] = 'id_product'
|
||||
ATTR_ID_PRODUCT_CATEGORY: ClassVar[str] = 'id_category'
|
||||
ATTR_ID_PRODUCT_IMAGE: ClassVar[str] = 'id_image'
|
||||
ATTR_ID_PRODUCT_PERMUTATION: ClassVar[str] = 'id_permutation'
|
||||
ATTR_ID_PRODUCT_PRICE: ClassVar[str] = 'id_price'
|
||||
ATTR_ID_PRODUCT_VARIATION: ClassVar[str] = 'id_variation'
|
||||
ATTR_ID_PRODUCT_VARIATION_TYPE: ClassVar[str] = 'id_type'
|
||||
ATTR_ID_STOCK_ITEM: ClassVar[str] = 'id_stock_item'
|
||||
ATTR_ID_STORAGE_LOCATION: ClassVar[str] = 'id_location'
|
||||
ATTR_ID_SUPPLIER: ClassVar[str] = 'id_supplier'
|
||||
ATTR_ID_SUPPLIER_ADDRESS: ClassVar[str] = 'id_address'
|
||||
ATTR_ID_SUPPLIER_PURCHASE_ORDER: ClassVar[str] = 'id_order'
|
||||
ATTR_ID_SUPPLIER_PURCHASE_ORDER_PRODUCT_LINK: ClassVar[str] = 'id_link'
|
||||
ATTR_ID_UNIT_MEASUREMENT_LATENCY_MANUFACTURE: ClassVar[str] = 'id_unit_latency_manufacture'
|
||||
ATTR_ID_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = 'id_unit_quantity'
|
||||
# FLAG_COST_LOCAL: ClassVar[str] = 'cost_local'
|
||||
FLAG_COST_TOTAL_LOCAL_VAT_EXCL: ClassVar[str] = 'cost_total_local_vat_excl'
|
||||
FLAG_COST_TOTAL_LOCAL_VAT_INCL: ClassVar[str] = 'cost_total_local_vat_incl'
|
||||
FLAG_COST_UNIT_LOCAL_VAT_EXCL: ClassVar[str] = 'cost_unit_local_vat_excl'
|
||||
FLAG_COST_UNIT_LOCAL_VAT_INCL: ClassVar[str] = 'cost_unit_local_vat_incl'
|
||||
FLAG_CUSTOMER: ClassVar[str] = 'customer'
|
||||
FLAG_CUSTOMER_ADDRESS: ClassVar[str] = 'customer_address'
|
||||
FLAG_CUSTOMER_SALES_ORDER: ClassVar[str] = 'customer_sales_order'
|
||||
FLAG_DELIVERY_OPTION: ClassVar[str] = 'delivery_option'
|
||||
FLAG_DISCOUNT: ClassVar[str] = 'discount'
|
||||
FLAG_HAS_VARIATIONS: ClassVar[str] = 'has_variations'
|
||||
FLAG_IS_OUT_OF_STOCK: ClassVar[str] = 'is_out_of_stock'
|
||||
FLAG_LATENCY_DELIVERY_DAYS: ClassVar[str] = 'latency_delivery_days'
|
||||
FLAG_LATENCY_MANUFACTURE: ClassVar[str] = 'latency_manufacture'
|
||||
FLAG_MANUFACTURING_PURCHASE_ORDER: ClassVar[str] = 'manufacturing_purchase_order'
|
||||
FLAG_ORDER_ITEMS: ClassVar[str] = 'order_items'
|
||||
FLAG_PLANT: ClassVar[str] = 'plant'
|
||||
FLAG_PRICE_TOTAL_LOCAL_VAT_EXCL: ClassVar[str] = 'price_total_local_vat_excl'
|
||||
FLAG_PRICE_TOTAL_LOCAL_VAT_INCL: ClassVar[str] = 'price_total_local_vat_incl'
|
||||
FLAG_PRICE_UNIT_LOCAL_VAT_EXCL: ClassVar[str] = 'price_unit_local_vat_excl'
|
||||
FLAG_PRICE_UNIT_LOCAL_VAT_INCL: ClassVar[str] = 'price_unit_local_vat_incl'
|
||||
FLAG_PRODUCT: ClassVar[str] = 'product'
|
||||
FLAG_PRODUCT_CATEGORY: ClassVar[str] = 'product_category'
|
||||
FLAG_PRODUCT_IMAGE: ClassVar[str] = 'product_image'
|
||||
FLAG_PRODUCT_PERMUTATION: ClassVar[str] = 'product_permutation'
|
||||
FLAG_PRODUCT_PRICE: ClassVar[str] = 'product_price'
|
||||
FLAG_PRODUCT_VARIATION: ClassVar[str] = 'product_variation'
|
||||
FLAG_PRODUCT_VARIATIONS: ClassVar[str] = f'{FLAG_PRODUCT_VARIATION}s'
|
||||
FLAG_PRODUCT_VARIATION_TYPE: ClassVar[str] = 'product_variation_type'
|
||||
FLAG_QUANTITY_MIN: ClassVar[str] = 'quantity_min'
|
||||
FLAG_QUANTITY_MAX: ClassVar[str] = 'quantity_max'
|
||||
FLAG_QUANTITY_ORDERED: ClassVar[str] = 'quantity_ordered'
|
||||
FLAG_QUANTITY_RECEIVED: ClassVar[str] = 'quantity_received'
|
||||
FLAG_STOCK_ITEM: ClassVar[str] = 'stock_item'
|
||||
FLAG_STORAGE_LOCATION: ClassVar[str] = 'storage_location'
|
||||
FLAG_SUPPLIER: ClassVar[str] = 'supplier'
|
||||
FLAG_SUPPLIER_ADDRESS: ClassVar[str] = 'supplier_address'
|
||||
FLAG_SUPPLIER_PURCHASE_ORDER: ClassVar[str] = 'supplier_purchase_order'
|
||||
FLAG_TEXT: ClassVar[str] = 'text'
|
||||
FLAG_UNIT_MEASUREMENT_LATENCY_MANUFACTURE: ClassVar[str] = 'unit_measurement_latency_manufacture'
|
||||
FLAG_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = 'unit_measurement_quantity'
|
||||
FLAG_VALUE_TEXT: ClassVar[str] = 'value_text'
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.__dict__)
|
||||
@@ -1,161 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Stripe Business Object
|
||||
|
||||
Description:
|
||||
Business objects for Stripe
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from lib import data_types
|
||||
from forms.forms import Form_Basket_Add, Form_Basket_Edit # Form_Product
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from datetime import datetime, timedelta
|
||||
import locale
|
||||
|
||||
class Stripe_Product(db.Model):
|
||||
id_product = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(255))
|
||||
description = db.Column(db.String(4000))
|
||||
price_GBP_full = db.Column(db.Float)
|
||||
id_category = db.Column(db.Integer)
|
||||
lead_time_manuf = db.Column(db.Integer)
|
||||
quantity_min = db.Column(db.Float)
|
||||
quantity_max = db.Column(db.Float)
|
||||
quantity_step = db.Column(db.Float)
|
||||
quantity_stock = db.Column(db.Float)
|
||||
id_stripe_product = db.Column(db.String(255))
|
||||
id_stripe_price = db.Column(db.String(255))
|
||||
is_subscription = db.Column(db.Boolean)
|
||||
name_recurring_interval = db.Column(db.String(255))
|
||||
name_plural_recurring_interval = db.Column(db.String(256))
|
||||
count_recurring_interval = db.Column(db.Integer)
|
||||
display_order = db.Column(db.Integer)
|
||||
can_view = db.Column(db.Boolean)
|
||||
can_edit = db.Column(db.Boolean)
|
||||
can_admin = db.Column(db.Boolean)
|
||||
# form_basket_add: Form_Basket_Add
|
||||
# form_basket_edit: Form_Basket_Edit
|
||||
|
||||
def __new__(cls, id, name, description, price_GBP_full, id_category, lead_time_manuf, quantity_min, quantity_max, quantity_step, quantity_stock, id_stripe_product, id_stripe_price,
|
||||
is_subscription, name_recurring_interval, name_plural_recurring_interval, count_recurring_interval, display_order, can_view, can_edit, can_admin):
|
||||
_m = 'Product.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
av.val_int(id, 'id', _m, 0, v_arg_type=v_arg_type)
|
||||
av.val_str(name, 'name', _m, max_len=256, v_arg_type=v_arg_type)
|
||||
av.val_str(description, 'description', _m, max_len=4000, v_arg_type=v_arg_type)
|
||||
av.full_val_float(price_GBP_full, 'price_GBP_full', _m, 0., v_arg_type=v_arg_type)
|
||||
av.val_int(id_category, 'id_category', _m, 0, v_arg_type=v_arg_type)
|
||||
av.val_int(lead_time_manuf, 'lead_time_manuf', _m, 0, v_arg_type=v_arg_type)
|
||||
av.full_val_float(quantity_step, 'quantity_step', _m, 0., v_arg_type=v_arg_type)
|
||||
av.full_val_float(quantity_min, 'quantity_min', _m, quantity_step, v_arg_type=v_arg_type)
|
||||
av.full_val_float(quantity_max, 'quantity_max', _m, quantity_min, v_arg_type=v_arg_type)
|
||||
av.full_val_float(quantity_stock, 'quantity_stock', _m, 0, v_arg_type=v_arg_type)
|
||||
av.val_str(id_stripe_product, 'id_stripe_product', _m, max_len=100, v_arg_type=v_arg_type)
|
||||
av.val_str(id_stripe_price, 'id_stripe_price', _m, max_len=100, v_arg_type=v_arg_type)
|
||||
av.full_val_bool(is_subscription, 'is_subscription', _m, v_arg_type=v_arg_type)
|
||||
Helper_App.console_log(f'is_subscription: {is_subscription}, {av.input_bool(is_subscription, "is_subscription", _m, v_arg_type=v_arg_type)}')
|
||||
is_subscription = av.input_bool(is_subscription, "is_subscription", _m, v_arg_type=v_arg_type)
|
||||
if is_subscription:
|
||||
av.val_str(name_recurring_interval, 'name_recurring_interval', _m, max_len=255, v_arg_type=v_arg_type)
|
||||
av.val_str(name_plural_recurring_interval, 'name_plural_recurring_interval', _m, max_len=256, v_arg_type=v_arg_type)
|
||||
av.val_int(count_recurring_interval, 'count_recurring_interval', _m, 0, v_arg_type=v_arg_type)
|
||||
av.val_int(display_order, 'display_order', _m, v_arg_type=v_arg_type)
|
||||
av.full_val_bool(can_view, 'can_view', _m, v_arg_type=v_arg_type)
|
||||
# can_view = av.input_bool(can_view, "can_view", _m, v_arg_type=v_arg_type)
|
||||
av.full_val_bool(can_edit, 'can_edit', _m, v_arg_type=v_arg_type)
|
||||
# can_edit = av.input_bool(can_edit, "can_edit", _m, v_arg_type=v_arg_type)
|
||||
av.full_val_bool(can_admin, 'can_admin', _m, v_arg_type=v_arg_type)
|
||||
# can_admin = av.input_bool(can_admin, "can_admin", _m, v_arg_type=v_arg_type)
|
||||
return super(Product, cls).__new__(cls) # , id, name, description, price_GBP, id_category, lead_time_manuf, quantity_min, quantity_max, quantity_step, quantity_stock, id_stripe_product, id_stripe_price,
|
||||
# is_subscription, name_recurring_interval, name_plural_recurring_interval, count_recurring_interval, can_view, can_edit, can_admin)
|
||||
|
||||
def __init__(self, id, name, description, price_GBP_full, id_category, lead_time_manuf, quantity_min, quantity_max, quantity_step, quantity_stock, id_stripe_product, id_stripe_price,
|
||||
is_subscription, name_recurring_interval, name_plural_recurring_interval, count_recurring_interval, display_order, can_view, can_edit, can_admin):
|
||||
_m = 'Product.__new__'
|
||||
v_arg_type = 'class attribute'
|
||||
self.id_product = id
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.price_GBP_full = price_GBP_full
|
||||
self.id_category = id_category
|
||||
self.lead_time_manuf = lead_time_manuf
|
||||
self.quantity_min = quantity_min
|
||||
self.quantity_max = quantity_max
|
||||
self.quantity_step = quantity_step
|
||||
self.quantity_stock = quantity_stock
|
||||
self.id_stripe_product = id_stripe_product
|
||||
self.id_stripe_price = id_stripe_price
|
||||
self.is_subscription = av.input_bool(is_subscription, "is_subscription", _m, v_arg_type=v_arg_type)
|
||||
self.name_recurring_interval = name_recurring_interval
|
||||
self.name_plural_recurring_interval = name_plural_recurring_interval
|
||||
self.count_recurring_interval = count_recurring_interval
|
||||
self.display_order = display_order
|
||||
self.can_view = av.input_bool(can_view, "can_view", _m, v_arg_type=v_arg_type)
|
||||
self.can_edit = av.input_bool(can_edit, "can_edit", _m, v_arg_type=v_arg_type)
|
||||
self.can_admin = av.input_bool(can_admin, "can_admin", _m, v_arg_type=v_arg_type)
|
||||
self.variations = []
|
||||
self.images = []
|
||||
self.delivery_options = []
|
||||
self.discounts = []
|
||||
self.discount_index = {}
|
||||
super().__init__()
|
||||
self.form_basket_add = Form_Basket_Add()
|
||||
self.form_basket_edit = Form_Basket_Edit()
|
||||
|
||||
def output_lead_time(self):
|
||||
return '1 day' if self.lead_time_manuf == 1 else f'{self.lead_time_manuf} days'
|
||||
|
||||
def output_delivery_date(self):
|
||||
return (datetime.now() + timedelta(days=self.lead_time_manuf)).strftime('%A, %d %B %Y')
|
||||
|
||||
def output_price(self):
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
return locale.format_string("%d", self.price_GBP_full, grouping=True)
|
||||
"""
|
||||
def add_form_basket_add(self):
|
||||
self.form_basket_add = None
|
||||
|
||||
def add_form_basket_edit(self):
|
||||
self.form_basket_edit = None
|
||||
"""
|
||||
def __repr__(self):
|
||||
return f'''Product
|
||||
id: {self.id_product}
|
||||
name: {self.name}
|
||||
description: {self.description}
|
||||
price_GBP_full: {self.price_GBP_full}
|
||||
id_category: {self.id_category}
|
||||
lead_time_manuf: {self.lead_time_manuf}
|
||||
quantity_min: {self.quantity_min}
|
||||
quantity_max: {self.quantity_max}
|
||||
quantity_step: {self.quantity_step}
|
||||
quantity_stock: {self.quantity_stock}
|
||||
id_stripe_product: {self.id_stripe_product}
|
||||
id_stripe_price: {self.id_stripe_price}
|
||||
is_subscription: {self.is_subscription}
|
||||
name_recurring_interval: {self.name_recurring_interval}
|
||||
name_plural_recurring_interval: {self.name_plural_recurring_interval}
|
||||
count_recurring_interval: {self.count_recurring_interval}
|
||||
display_order: {self.display_order}
|
||||
can_view: {self.can_view}
|
||||
can_edit: {self.can_edit}
|
||||
can_admin: {self.can_admin}
|
||||
variations: {self.variations}
|
||||
images: {self.images}
|
||||
delivery_options: {self.delivery_options}
|
||||
'''
|
||||
|
||||
def add_product_price_discount(self, discount):
|
||||
_m = 'Category.add_product'
|
||||
av.val_instance(discount, 'discount', _m, Discount)
|
||||
# self.product_index.append(len(self.products))
|
||||
self.discount_index[discount.id_discount] = len(self.discounts)
|
||||
self.discounts.append(discount)
|
||||
@@ -1,200 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Supplier Business Object
|
||||
|
||||
Description:
|
||||
Business object for supplier
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.store.supplier_address import Supplier_Address
|
||||
from business_objects.currency import Currency
|
||||
from business_objects.db_base import Get_Many_Parameters_Base
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from pydantic import BaseModel
|
||||
from typing import ClassVar
|
||||
|
||||
|
||||
class Supplier(db.Model, Store_Base):
|
||||
FLAG_DEPARTMENT_CONTACT: ClassVar[str] = 'department_contact'
|
||||
FLAG_NAME_COMPANY: ClassVar[str] = 'name_company'
|
||||
FLAG_NAME_CONTACT: ClassVar[str] = 'name_contact'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_SUPPLIER
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = FLAG_NAME_COMPANY
|
||||
__tablename__ = 'Shop_Supplier'
|
||||
id_supplier = db.Column(db.Integer, primary_key=True)
|
||||
# id_address = db.Column(db.Integer)
|
||||
id_currency = db.Column(db.Integer)
|
||||
name_company = db.Column(db.String(255))
|
||||
name_contact = db.Column(db.String(255))
|
||||
department_contact = db.Column(db.String(255))
|
||||
phone_number = db.Column(db.String(50))
|
||||
fax = db.Column(db.String(50))
|
||||
email = db.Column(db.String(255))
|
||||
website = db.Column(db.String(255))
|
||||
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)
|
||||
self.addresses = []
|
||||
self.currency = None
|
||||
@classmethod
|
||||
def from_DB_supplier(cls, query_row):
|
||||
supplier = cls()
|
||||
supplier.id_supplier = query_row[0]
|
||||
# supplier.id_address = query_row[1]
|
||||
# supplier.address = Supplier_Address.from_DB_supplier(query_row)
|
||||
supplier.id_currency = query_row[1]
|
||||
supplier.currency = Currency.from_DB_supplier(query_row)
|
||||
supplier.name_company = query_row[4]
|
||||
supplier.name_contact = query_row[5]
|
||||
supplier.department_contact = query_row[6]
|
||||
supplier.phone_number = query_row[7]
|
||||
supplier.fax = query_row[8]
|
||||
supplier.email = query_row[9]
|
||||
supplier.website = query_row[10]
|
||||
supplier.active = av.input_bool(query_row[11], 'active', f'{cls.__name__}.from_DB_supplier')
|
||||
return supplier
|
||||
@classmethod
|
||||
def from_DB_supplier_purchase_order(cls, query_row):
|
||||
supplier = cls()
|
||||
supplier.id_supplier = query_row[1]
|
||||
supplier.name_company = query_row[2]
|
||||
return supplier
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id: {self.id_supplier},
|
||||
id_currency: {self.id_currency},
|
||||
name_company: {self.name_company},
|
||||
name_contact: {self.name_contact},
|
||||
department_contact: {self.department_contact},
|
||||
phone_number: {self.phone_number},
|
||||
fax: {self.fax},
|
||||
email: {self.email},
|
||||
website: {self.website},
|
||||
active: {self.active},
|
||||
addresses: {self.addresses}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_SUPPLIER: self.id_supplier,
|
||||
# self.ATTR_ID_ADDRESS: self.id_address,
|
||||
self.ATTR_ID_CURRENCY: self.id_currency,
|
||||
self.FLAG_NAME_COMPANY: self.name_company,
|
||||
self.FLAG_NAME_CONTACT: self.name_contact,
|
||||
self.FLAG_DEPARTMENT_CONTACT: self.department_contact,
|
||||
self.FLAG_PHONE_NUMBER: self.phone_number,
|
||||
self.FLAG_FAX: self.fax,
|
||||
self.FLAG_EMAIL: self.email,
|
||||
self.FLAG_WEBSITE: self.website,
|
||||
self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json')
|
||||
}
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_supplier,
|
||||
'text': self.name_company
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
|
||||
supplier = cls()
|
||||
supplier.id_supplier = json[cls.ATTR_ID_SUPPLIER]
|
||||
supplier.id_currency = json[cls.ATTR_ID_CURRENCY]
|
||||
supplier.name_company = json[cls.FLAG_NAME_COMPANY]
|
||||
supplier.name_contact = json[cls.FLAG_NAME_CONTACT]
|
||||
supplier.department_contact = json[cls.FLAG_DEPARTMENT_CONTACT]
|
||||
supplier.phone_number = json[cls.FLAG_PHONE_NUMBER]
|
||||
supplier.fax = json[cls.FLAG_FAX]
|
||||
supplier.email = json[cls.FLAG_EMAIL]
|
||||
supplier.website = json[cls.FLAG_WEBSITE]
|
||||
supplier.active = json[cls.FLAG_ACTIVE]
|
||||
addresses = json.get(cls.FLAG_SUPPLIER_ADDRESS, [])
|
||||
supplier.addresses = [Supplier_Address.from_json(address) for address in addresses]
|
||||
return supplier
|
||||
def get_address_active(self):
|
||||
for address in self.addresses:
|
||||
if address.active:
|
||||
return address
|
||||
return Supplier_Address()
|
||||
address = Supplier_Address()
|
||||
address.postcode = ''
|
||||
return address
|
||||
|
||||
class Parameters_Supplier(Get_Many_Parameters_Base):
|
||||
a_get_all_supplier: bool
|
||||
a_get_inactive_supplier: bool
|
||||
a_ids_supplier: str
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
return cls(
|
||||
a_get_all_supplier = True,
|
||||
a_get_inactive_supplier = False,
|
||||
a_ids_supplier = '',
|
||||
)
|
||||
@classmethod
|
||||
def from_filters_supplier(cls, form):
|
||||
parameters = cls.get_default()
|
||||
parameters.a_get_inactive_supplier = form.active.data
|
||||
return parameters
|
||||
|
||||
class Supplier_Temp(db.Model, Store_Base):
|
||||
__tablename__: ClassVar[str] = 'Shop_Supplier_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_supplier: int = db.Column(db.Integer)
|
||||
id_currency: int = db.Column(db.Integer)
|
||||
# id_address: int = db.Column(db.Integer)
|
||||
name_company: str = db.Column(db.String(255))
|
||||
name_contact: str = db.Column(db.String(255))
|
||||
department_contact: str = db.Column(db.String(255))
|
||||
phone_number: str = db.Column(db.String(50))
|
||||
fax: str = db.Column(db.String(50))
|
||||
email: str = db.Column(db.String(255))
|
||||
website: str = db.Column(db.String(255))
|
||||
active: bool = db.Column(db.Boolean)
|
||||
guid: str = db.Column(db.String(36))
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_supplier(cls, supplier):
|
||||
row = cls()
|
||||
row.id_supplier = supplier.id_supplier
|
||||
row.id_currency = supplier.id_currency
|
||||
# row.id_address = supplier.id_address
|
||||
row.name_company = supplier.name_company
|
||||
row.name_contact = supplier.name_contact
|
||||
row.department_contact = supplier.department_contact
|
||||
row.phone_number = supplier.phone_number
|
||||
row.fax = supplier.fax
|
||||
row.email = supplier.email
|
||||
row.website = supplier.website
|
||||
row.active = 1 if supplier.active else 0
|
||||
return row
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id_supplier: {self.id_supplier}
|
||||
id_currency: {self.id_currency}
|
||||
name_company: {self.name_company}
|
||||
name_contact: {self.name_contact}
|
||||
department_contact: {self.department_contact}
|
||||
phone_number: {self.phone_number}
|
||||
fax: {self.fax}
|
||||
email: {self.email}
|
||||
website: {self.website}
|
||||
active: {self.active}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
@@ -1,146 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Supplier Address Business Object
|
||||
|
||||
Description:
|
||||
Business object for supplier address
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from business_objects.region import Region
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from typing import ClassVar
|
||||
from flask import jsonify
|
||||
|
||||
class Supplier_Address(db.Model, Store_Base):
|
||||
FLAG_ADDRESS_LINE_1: ClassVar[str] = 'address_line_1'
|
||||
FLAG_ADDRESS_LINE_2: ClassVar[str] = 'address_line_2'
|
||||
FLAG_CITY: ClassVar[str] = 'city'
|
||||
FLAG_COUNTY: ClassVar[str] = 'county'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_ADDRESS
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_POSTCODE
|
||||
__tablename__ = 'Shop_Supplier_Address'
|
||||
id_address = db.Column(db.Integer, primary_key=True)
|
||||
id_supplier = db.Column(db.Integer)
|
||||
id_region = db.Column(db.Integer)
|
||||
postcode = db.Column(db.String(20))
|
||||
address_line_1 = db.Column(db.String(256))
|
||||
address_line_2 = db.Column(db.String(256))
|
||||
city = db.Column(db.String(256))
|
||||
county = db.Column(db.String(256))
|
||||
active = db.Column(db.Boolean)
|
||||
|
||||
# region = None
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
self.region = Region()
|
||||
@classmethod
|
||||
def from_DB_supplier(cls, query_row):
|
||||
address = cls()
|
||||
address.id_supplier = query_row[0]
|
||||
address.id_address = query_row[1]
|
||||
address.id_region = query_row[2]
|
||||
address.region = Region.from_DB_supplier(query_row)
|
||||
address.postcode = query_row[4]
|
||||
address.address_line_1 = query_row[5]
|
||||
address.address_line_2 = query_row[6]
|
||||
address.city = query_row[7]
|
||||
address.county = query_row[8]
|
||||
address.active = av.input_bool(query_row[9], 'active', f'{cls.__name__}.from_DB_supplier')
|
||||
|
||||
return address
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.ATTR_ID_ADDRESS}: {self.id_address}
|
||||
{self.ATTR_ID_SUPPLIER}: {self.id_supplier}
|
||||
{self.FLAG_REGION}: {self.region}
|
||||
{self.FLAG_POSTCODE}: {self.postcode}
|
||||
{self.FLAG_ADDRESS_LINE_1}: {self.address_line_1}
|
||||
{self.FLAG_ADDRESS_LINE_2}: {self.address_line_2}
|
||||
{self.FLAG_CITY}: {self.city}
|
||||
{self.FLAG_COUNTY}: {self.county}
|
||||
{self.FLAG_ACTIVE}: {self.active}
|
||||
'''
|
||||
def to_json(self):
|
||||
Helper_App.console_log(f'{self.__class__.__name__}.to_json\n{self.__dict__}\n{self}')
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_ADDRESS: self.id_address,
|
||||
self.ATTR_ID_SUPPLIER: self.id_supplier,
|
||||
self.FLAG_REGION: self.region.to_json(),
|
||||
self.FLAG_POSTCODE: self.postcode,
|
||||
self.FLAG_ADDRESS_LINE_1: self.address_line_1,
|
||||
self.FLAG_ADDRESS_LINE_2: self.address_line_2,
|
||||
self.FLAG_CITY: self.city,
|
||||
self.FLAG_COUNTY: self.county,
|
||||
self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0
|
||||
}
|
||||
def to_json_str(self):
|
||||
return jsonify(self.to_json())
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
|
||||
address = cls()
|
||||
address.id_address = json[cls.ATTR_ID_ADDRESS]
|
||||
address.id_supplier = json[cls.ATTR_ID_SUPPLIER]
|
||||
address.id_region = json[cls.ATTR_ID_REGION]
|
||||
address.region = Region()
|
||||
address.region.id_region = json[cls.ATTR_ID_REGION]
|
||||
address.postcode = json[cls.FLAG_POSTCODE]
|
||||
address.address_line_1 = json[cls.FLAG_ADDRESS_LINE_1]
|
||||
address.address_line_2 = json.get(cls.FLAG_ADDRESS_LINE_2, '')
|
||||
address.city = json[cls.FLAG_CITY]
|
||||
address.county = json[cls.FLAG_COUNTY]
|
||||
address.active = json[cls.FLAG_ACTIVE]
|
||||
return address
|
||||
|
||||
|
||||
class Supplier_Address_Temp(db.Model, Store_Base):
|
||||
__tablename__: ClassVar[str] = 'Shop_Supplier_Address_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_address: int = db.Column(db.Integer, primary_key=True)
|
||||
id_supplier: int = db.Column(db.Integer)
|
||||
id_region: int = db.Column(db.Integer)
|
||||
postcode: str = db.Column(db.String(20))
|
||||
address_line_1: str = db.Column(db.String(256))
|
||||
address_line_2: str = db.Column(db.String(256))
|
||||
city: str = db.Column(db.String(256))
|
||||
county: str = db.Column(db.String(256))
|
||||
active: bool = db.Column(db.Boolean)
|
||||
guid: str = db.Column(db.String(36))
|
||||
@classmethod
|
||||
def from_supplier_address(cls, address):
|
||||
row = cls()
|
||||
row.id_address = address.id_address
|
||||
row.id_supplier = address.id_supplier
|
||||
row.id_region = address.id_region
|
||||
row.postcode = address.postcode
|
||||
row.address_line_1 = address.address_line_1
|
||||
row.address_line_2 = address.address_line_2
|
||||
row.city = address.city
|
||||
row.county = address.county
|
||||
row.active = 1 if address.active else 0
|
||||
return row
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id_address: {self.id_address}
|
||||
id_supplier: {self.id_supplier}
|
||||
id_region: {self.id_region}
|
||||
postcode: {self.postcode}
|
||||
address_line_1: {self.address_line_1}
|
||||
address_line_2: {self.address_line_2}
|
||||
city: {self.city}
|
||||
county: {self.county}
|
||||
active: {self.active}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
@@ -1,343 +0,0 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Supplier_Purchase_Order Business Object
|
||||
|
||||
Description:
|
||||
Business object for supplier_purchase_order
|
||||
"""
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.currency import Currency
|
||||
from business_objects.db_base import Get_Many_Parameters_Base
|
||||
from business_objects.store.store_base import Store_Base
|
||||
from business_objects.store.supplier import Supplier
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from pydantic import BaseModel
|
||||
from typing import ClassVar, Optional
|
||||
from datetime import datetime
|
||||
|
||||
class Supplier_Purchase_Order(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_SUPPLIER_PURCHASE_ORDER
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
|
||||
__tablename__ = 'Shop_Supplier_Purchase_Order'
|
||||
id_order = db.Column(db.Integer, primary_key=True)
|
||||
id_supplier = db.Column(db.Integer)
|
||||
id_currency = db.Column(db.Integer)
|
||||
cost_total_local_VAT_excl = db.Column(db.Float)
|
||||
cost_total_local_VAT_incl = db.Column(db.Float)
|
||||
active = db.Column(db.Boolean)
|
||||
created_on = db.Column(db.DateTime)
|
||||
created_by = db.Column(db.Integer)
|
||||
name = db.Column(db.String(255))
|
||||
# items: list = None
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
Store_Base.__init__(self)
|
||||
self.currency = None
|
||||
self.items = []
|
||||
self.supplier = None
|
||||
@classmethod
|
||||
def from_DB_supplier_purchase_order(cls, query_row):
|
||||
supplier_purchase_order = cls()
|
||||
supplier_purchase_order.id_order = query_row[0]
|
||||
supplier_purchase_order.id_supplier = query_row[1]
|
||||
supplier_purchase_order.supplier = Supplier.from_DB_supplier_purchase_order(query_row)
|
||||
supplier_purchase_order.id_currency = query_row[3]
|
||||
supplier_purchase_order.currency = Currency.from_DB_supplier_purchase_order(query_row)
|
||||
supplier_purchase_order.cost_total_local_VAT_excl = query_row[6]
|
||||
supplier_purchase_order.cost_total_local_VAT_incl = query_row[7]
|
||||
supplier_purchase_order.active = av.input_bool(query_row[8], 'active', f'{cls.__name__}.from_DB_supplier_purchase_order')
|
||||
supplier_purchase_order.created_on = query_row[9]
|
||||
supplier_purchase_order.name = query_row[10]
|
||||
return supplier_purchase_order
|
||||
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.ATTR_ID_SUPPLIER_PURCHASE_ORDER}: {self.id_order},
|
||||
{self.ATTR_ID_SUPPLIER}: {self.id_supplier},
|
||||
{self.FLAG_SUPPLIER}: {self.supplier},
|
||||
{self.ATTR_ID_CURRENCY}: {self.id_currency},
|
||||
{self.FLAG_CURRENCY}: {self.currency},
|
||||
{self.FLAG_COST_TOTAL_LOCAL_VAT_EXCL}: {self.cost_total_local_VAT_excl},
|
||||
{self.FLAG_COST_TOTAL_LOCAL_VAT_INCL}: {self.cost_total_local_VAT_incl},
|
||||
{self.FLAG_ACTIVE}: {self.active},
|
||||
{self.FLAG_CREATED_ON}: {self.created_on},
|
||||
{self.FLAG_NAME}: {self.name}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_SUPPLIER_PURCHASE_ORDER: self.id_order,
|
||||
self.ATTR_ID_SUPPLIER: self.id_supplier,
|
||||
self.FLAG_SUPPLIER: self.supplier.to_json(),
|
||||
self.ATTR_ID_CURRENCY: self.id_currency,
|
||||
self.FLAG_CURRENCY: self.currency.to_json(),
|
||||
self.FLAG_COST_TOTAL_LOCAL_VAT_EXCL: self.cost_total_local_VAT_excl,
|
||||
self.FLAG_COST_TOTAL_LOCAL_VAT_INCL: self.cost_total_local_VAT_incl,
|
||||
self.FLAG_ORDER_ITEMS: [item.to_json() for item in self.items],
|
||||
self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'),
|
||||
self.FLAG_CREATED_ON: self.created_on,
|
||||
self.FLAG_NAME: self.name,
|
||||
}
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_order,
|
||||
'text': self.name,
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
|
||||
supplier_purchase_order = cls()
|
||||
supplier_purchase_order.id_order = json[cls.ATTR_ID_SUPPLIER_PURCHASE_ORDER]
|
||||
supplier_purchase_order.id_supplier = json[cls.ATTR_ID_SUPPLIER]
|
||||
supplier_purchase_order.id_currency = json[cls.ATTR_ID_CURRENCY]
|
||||
supplier_purchase_order.cost_total_local_VAT_excl = json[cls.FLAG_COST_TOTAL_LOCAL_VAT_EXCL]
|
||||
supplier_purchase_order.cost_total_local_VAT_incl = json[cls.FLAG_COST_TOTAL_LOCAL_VAT_INCL]
|
||||
supplier_purchase_order.items = [Supplier_Purchase_Order_Product_Link.from_json(item) for item in json[cls.FLAG_ORDER_ITEMS]]
|
||||
supplier_purchase_order.active = json[cls.FLAG_ACTIVE]
|
||||
supplier_purchase_order.created_on = json.get(cls.FLAG_CREATED_ON, None)
|
||||
supplier_purchase_order.created_by = json.get(cls.FLAG_CREATED_BY, None)
|
||||
supplier_purchase_order.name = json.get(cls.FLAG_NAME, None)
|
||||
return supplier_purchase_order
|
||||
|
||||
class Supplier_Purchase_Order_Product_Link(db.Model, Store_Base):
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_SUPPLIER_PURCHASE_ORDER_PRODUCT_LINK
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
|
||||
__tablename__ = 'Shop_Supplier_Purchase_Order_Product_Link'
|
||||
id_link = db.Column(db.Integer, primary_key=True)
|
||||
id_order = db.Column(db.Integer)
|
||||
id_category = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
csv_id_pairs_variation = db.Column(db.String)
|
||||
id_unit_quantity = db.Column(db.Integer)
|
||||
name_permutation = db.Column(db.String(255))
|
||||
quantity_ordered = db.Column(db.Float)
|
||||
quantity_received = db.Column(db.Float)
|
||||
latency_delivery_days = db.Column(db.Integer)
|
||||
display_order = db.Column(db.Integer)
|
||||
cost_total_local_VAT_excl = db.Column(db.Float)
|
||||
cost_total_local_VAT_incl = db.Column(db.Float)
|
||||
cost_unit_local_VAT_excl = db.Column(db.Float)
|
||||
cost_unit_local_VAT_incl = db.Column(db.Float)
|
||||
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)
|
||||
# self.unit_quantity = None
|
||||
@classmethod
|
||||
def from_DB_supplier_purchase_order(cls, query_row):
|
||||
link = cls()
|
||||
link.id_link = query_row[0]
|
||||
link.id_order = query_row[1]
|
||||
link.id_category = query_row[2]
|
||||
link.id_product = query_row[3]
|
||||
link.id_permutation = query_row[4]
|
||||
link.name_permutation = query_row[5]
|
||||
link.csv_id_pairs_variation = query_row[6]
|
||||
link.id_unit_quantity = query_row[7]
|
||||
link.quantity_ordered = query_row[8]
|
||||
link.quantity_received = query_row[9]
|
||||
link.latency_delivery_days = query_row[10]
|
||||
link.display_order = query_row[11]
|
||||
link.cost_total_local_VAT_excl = query_row[12]
|
||||
link.cost_total_local_VAT_incl = query_row[13]
|
||||
link.cost_unit_local_VAT_excl = query_row[14]
|
||||
link.cost_unit_local_VAT_incl = query_row[15]
|
||||
link.active = query_row[16]
|
||||
return link
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.ATTR_ID_SUPPLIER_PURCHASE_ORDER_PRODUCT_LINK}: {self.id_link},
|
||||
{self.ATTR_ID_SUPPLIER_PURCHASE_ORDER}: {self.id_order},
|
||||
{self.ATTR_ID_PRODUCT_CATEGORY}: {self.id_category},
|
||||
{self.ATTR_ID_PRODUCT}: {self.id_product},
|
||||
{self.ATTR_ID_PRODUCT_PERMUTATION}: {self.id_permutation},
|
||||
{self.FLAG_NAME}: {self.name_permutation},
|
||||
{self.FLAG_PRODUCT_VARIATIONS}: {self.csv_id_pairs_variation},
|
||||
{self.ATTR_ID_UNIT_MEASUREMENT_QUANTITY}: {self.id_unit_quantity},
|
||||
{self.FLAG_QUANTITY_ORDERED}: {self.quantity_ordered},
|
||||
{self.FLAG_QUANTITY_RECEIVED}: {self.quantity_received},
|
||||
{self.FLAG_LATENCY_DELIVERY_DAYS}: {self.latency_delivery_days},
|
||||
{self.FLAG_DISPLAY_ORDER}: {self.display_order},
|
||||
{self.FLAG_COST_TOTAL_LOCAL_VAT_EXCL}: {self.cost_total_local_VAT_excl},
|
||||
{self.FLAG_COST_TOTAL_LOCAL_VAT_INCL}: {self.cost_total_local_VAT_incl},
|
||||
{self.FLAG_COST_UNIT_LOCAL_VAT_EXCL}: {self.cost_unit_local_VAT_excl},
|
||||
{self.FLAG_COST_UNIT_LOCAL_VAT_INCL}: {self.cost_unit_local_VAT_incl},
|
||||
{self.FLAG_ACTIVE}: {self.active}
|
||||
'''
|
||||
def to_json(self):
|
||||
return {
|
||||
**self.get_shared_json_attributes(self),
|
||||
self.ATTR_ID_SUPPLIER_PURCHASE_ORDER_PRODUCT_LINK: self.id_link,
|
||||
self.ATTR_ID_SUPPLIER_PURCHASE_ORDER: self.id_order,
|
||||
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
|
||||
self.ATTR_ID_PRODUCT: self.id_product,
|
||||
self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation,
|
||||
self.FLAG_NAME: self.name_permutation,
|
||||
self.FLAG_PRODUCT_VARIATIONS: self.csv_id_pairs_variation,
|
||||
self.ATTR_ID_UNIT_MEASUREMENT_QUANTITY: self.id_unit_quantity,
|
||||
self.FLAG_QUANTITY_ORDERED: self.quantity_ordered,
|
||||
self.FLAG_QUANTITY_RECEIVED: self.quantity_received,
|
||||
self.FLAG_LATENCY_DELIVERY_DAYS: self.latency_delivery_days,
|
||||
self.FLAG_DISPLAY_ORDER: self.display_order,
|
||||
self.FLAG_COST_TOTAL_LOCAL_VAT_EXCL: self.cost_total_local_VAT_excl,
|
||||
self.FLAG_COST_TOTAL_LOCAL_VAT_INCL: self.cost_total_local_VAT_incl,
|
||||
self.FLAG_COST_UNIT_LOCAL_VAT_EXCL: self.cost_unit_local_VAT_excl,
|
||||
self.FLAG_COST_UNIT_LOCAL_VAT_INCL: self.cost_unit_local_VAT_incl,
|
||||
self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'),
|
||||
}
|
||||
def to_json_option(self):
|
||||
return {
|
||||
'value': self.id_order,
|
||||
'text': self.name_permutation,
|
||||
}
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
Helper_App.console_log(f'{cls.__name__}.from_json: {json}')
|
||||
link = cls()
|
||||
link.id_link = json[cls.ATTR_ID_SUPPLIER_PURCHASE_ORDER_PRODUCT_LINK]
|
||||
link.id_order = json[cls.ATTR_ID_SUPPLIER_PURCHASE_ORDER]
|
||||
link.id_category = json.get(cls.ATTR_ID_PRODUCT_CATEGORY, None)
|
||||
link.id_product = json.get(cls.ATTR_ID_PRODUCT, None)
|
||||
link.id_permutation = json.get(cls.ATTR_ID_PRODUCT_PERMUTATION, None)
|
||||
link.name_permutation = json.get(cls.FLAG_NAME, None)
|
||||
link.csv_id_pairs_variation = json.get(cls.FLAG_PRODUCT_VARIATIONS, '')
|
||||
link.id_unit_quantity = json[cls.ATTR_ID_UNIT_MEASUREMENT_QUANTITY]
|
||||
link.quantity_ordered = json[cls.FLAG_QUANTITY_ORDERED]
|
||||
link.quantity_received = json[cls.FLAG_QUANTITY_RECEIVED]
|
||||
link.latency_delivery_days = json[cls.FLAG_LATENCY_DELIVERY_DAYS]
|
||||
link.display_order = json[cls.FLAG_DISPLAY_ORDER]
|
||||
link.cost_total_local_VAT_excl = json[cls.FLAG_COST_TOTAL_LOCAL_VAT_EXCL]
|
||||
link.cost_total_local_VAT_incl = json[cls.FLAG_COST_TOTAL_LOCAL_VAT_INCL]
|
||||
link.cost_unit_local_VAT_excl = json.get(cls.FLAG_COST_UNIT_LOCAL_VAT_EXCL, None)
|
||||
link.cost_unit_local_VAT_incl = json.get(cls.FLAG_COST_UNIT_LOCAL_VAT_INCL, None)
|
||||
link.active = json[cls.FLAG_ACTIVE]
|
||||
return link
|
||||
|
||||
class Parameters_Supplier_Purchase_Order(Get_Many_Parameters_Base):
|
||||
a_get_all_supplier: bool
|
||||
a_get_inactive_supplier: bool
|
||||
a_ids_supplier: str
|
||||
a_get_all_order: bool
|
||||
a_get_inactive_order: bool
|
||||
a_ids_order: str
|
||||
a_ids_permutation: str
|
||||
a_date_from: Optional[datetime]
|
||||
a_date_to: Optional[datetime]
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
return cls(
|
||||
a_get_all_supplier = True,
|
||||
a_get_inactive_supplier = False,
|
||||
a_ids_supplier = '',
|
||||
a_get_all_order = True,
|
||||
a_get_inactive_order = False,
|
||||
a_ids_order = '',
|
||||
a_ids_permutation = '',
|
||||
a_date_from = None,
|
||||
a_date_to = None
|
||||
)
|
||||
@classmethod
|
||||
def from_filters_supplier_purchase_order(cls, form):
|
||||
parameters = cls.get_default()
|
||||
parameters.a_get_inactive_order = form.active.data
|
||||
parameters.a_date_from = None if form.date_from.data == '' else form.date_from.data
|
||||
parameters.a_date_to = None if form.date_to.data == '' else form.date_to.data
|
||||
return parameters
|
||||
|
||||
class Supplier_Purchase_Order_Temp(db.Model, Store_Base):
|
||||
__tablename__: ClassVar[str] = 'Shop_Supplier_Purchase_Order_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_order: int = db.Column(db.Integer)
|
||||
id_supplier_ordered: int = db.Column(db.Integer)
|
||||
id_currency_cost: int = db.Column(db.Integer)
|
||||
active: bool = db.Column(db.Boolean)
|
||||
guid: str = db.Column(db.String(36))
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_supplier_purchase_order(cls, supplier_purchase_order):
|
||||
row = cls()
|
||||
row.id_order = supplier_purchase_order.id_order
|
||||
row.id_supplier_ordered = supplier_purchase_order.id_supplier
|
||||
row.id_currency_cost = supplier_purchase_order.id_currency
|
||||
row.active = 1 if supplier_purchase_order.active else 0
|
||||
return row
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id_order: {self.id_order}
|
||||
id_supplier_ordered: {self.id_supplier_ordered}
|
||||
id_currency_cost: {self.id_currency_cost}
|
||||
active: {self.active}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
|
||||
class Supplier_Purchase_Order_Product_Link_Temp(db.Model, Store_Base):
|
||||
__tablename__: ClassVar[str] = 'Shop_Supplier_Purchase_Order_Product_Link_Temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
id_temp: int = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||
id_link = db.Column(db.Integer)
|
||||
id_order = db.Column(db.Integer)
|
||||
id_product = db.Column(db.Integer)
|
||||
id_permutation = db.Column(db.Integer)
|
||||
csv_list_variations = db.Column(db.String)
|
||||
id_unit_quantity = db.Column(db.Integer)
|
||||
quantity_ordered = db.Column(db.Float)
|
||||
quantity_received = db.Column(db.Float)
|
||||
latency_delivery_days = db.Column(db.Integer)
|
||||
display_order = db.Column(db.Integer)
|
||||
cost_total_local_VAT_excl = db.Column(db.Float)
|
||||
cost_total_local_VAT_incl = db.Column(db.Float)
|
||||
active = db.Column(db.Boolean)
|
||||
guid = db.Column(db.String(36))
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.id_temp = None
|
||||
@classmethod
|
||||
def from_supplier_purchase_order_product_link(cls, supplier_purchase_order_product_link):
|
||||
row = cls()
|
||||
row.id_link = supplier_purchase_order_product_link.id_link
|
||||
row.id_order = supplier_purchase_order_product_link.id_order
|
||||
row.id_product = supplier_purchase_order_product_link.id_product
|
||||
row.id_permutation = supplier_purchase_order_product_link.id_permutation
|
||||
row.csv_list_variations = supplier_purchase_order_product_link.csv_id_pairs_variation
|
||||
row.id_unit_quantity = supplier_purchase_order_product_link.id_unit_quantity
|
||||
row.quantity_ordered = supplier_purchase_order_product_link.quantity_ordered
|
||||
row.quantity_received = supplier_purchase_order_product_link.quantity_received
|
||||
row.latency_delivery_days = supplier_purchase_order_product_link.latency_delivery_days
|
||||
row.display_order = supplier_purchase_order_product_link.display_order
|
||||
row.cost_total_local_VAT_excl = supplier_purchase_order_product_link.cost_total_local_VAT_excl
|
||||
row.cost_total_local_VAT_incl = supplier_purchase_order_product_link.cost_total_local_VAT_incl
|
||||
row.active = 1 if supplier_purchase_order_product_link.active else 0
|
||||
return row
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
id_link: {self.id_link}
|
||||
id_order: {self.id_order}
|
||||
id_product: {self.id_product}
|
||||
id_permutation: {self.id_permutation}
|
||||
csv_list_variations: {self.csv_list_variations}
|
||||
id_unit_quantity: {self.id_unit_quantity}
|
||||
quantity_ordered: {self.quantity_ordered}
|
||||
quantity_received: {self.quantity_received}
|
||||
latency_delivery_days: {self.latency_delivery_days}
|
||||
display_order: {self.display_order}
|
||||
cost_total_local_VAT_excl: {self.cost_total_local_VAT_excl}
|
||||
cost_total_local_VAT_incl: {self.cost_total_local_VAT_incl}
|
||||
active: {self.active}
|
||||
guid: {self.guid}
|
||||
'''
|
||||
Reference in New Issue
Block a user