New website focusing on ERP services.

This commit is contained in:
2025-01-15 23:52:09 +00:00
parent 120cccd0d5
commit d1b90db6d7
207 changed files with 3827 additions and 24667 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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}
'''

View File

@@ -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}
'''

View File

@@ -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

View File

@@ -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}
'''

View File

@@ -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}
'''

View File

@@ -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

View File

@@ -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}
'''

View File

@@ -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__)

View File

@@ -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
}
"""

View File

@@ -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

View File

@@ -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,
}

View File

@@ -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

View File

@@ -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}
'''

View File

@@ -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}
'''

View File

@@ -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}'

View File

@@ -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__)

View File

@@ -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)

View File

@@ -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}
'''

View File

@@ -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}
'''

View File

@@ -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}
'''