|
|
@@ -9,7 +9,7 @@ from openpyxl import load_workbook
|
|
|
from pydantic import ValidationError
|
|
|
|
|
|
from app.git import git_add_commit
|
|
|
-from app.parser import read_dir, read_file
|
|
|
+from app.parser import read_dir, read_file, parse_file
|
|
|
from app.schema import (
|
|
|
CartOrderInfo,
|
|
|
CartSession,
|
|
|
@@ -19,11 +19,10 @@ from app.schema import (
|
|
|
DocumentProductMeta,
|
|
|
OrdersBlock,
|
|
|
ShippingInfo,
|
|
|
- create_product_id,
|
|
|
Settings,
|
|
|
- ProductShippingMeta,
|
|
|
+ ProductShippingMeta,
|
|
|
)
|
|
|
-from app.serializer import convert_pydantic_product_to_text, format_yaml_multiline, format_order_items, format_order_shipping_info
|
|
|
+from app.serializer import convert_pydantic_product_to_text, format_order_items, format_order_shipping_info
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@@ -46,43 +45,36 @@ def check_product_availability(
|
|
|
is_selectable = False
|
|
|
amount = 0
|
|
|
|
|
|
- # we might receive a GET request from /products/<product-id> for a
|
|
|
- # product with options but no option has been selected yet, cause
|
|
|
- # the user just navigated to the page. in this case we can't make
|
|
|
- # any filtering based on the options fields, so we just return the
|
|
|
- # product to be available.
|
|
|
- if product.meta.options and size is None and style is None:
|
|
|
- is_available = True
|
|
|
- is_selectable = True
|
|
|
-
|
|
|
+ if style or size:
|
|
|
+ product_variation_id = get_variation_id(product, size, style)
|
|
|
else:
|
|
|
- selected_inventory = [
|
|
|
- inventory
|
|
|
- for inventory in product.meta.inventory
|
|
|
- if inventory.size == size and inventory.style == style
|
|
|
- ]
|
|
|
-
|
|
|
- if len(selected_inventory) > 0:
|
|
|
- for model in selected_inventory:
|
|
|
- if model.size == size and model.style == style:
|
|
|
- is_available = model.amount > 0
|
|
|
-
|
|
|
- # we check if the user's requested quantity for the given item is
|
|
|
- # between 1 and <= the model inventory's amount value
|
|
|
- is_selectable = (
|
|
|
- model.amount - quantity > 0 and quantity <= model.amount
|
|
|
- )
|
|
|
- amount = model.amount
|
|
|
+ product_variation_id = None
|
|
|
+
|
|
|
+ if product_variation_id:
|
|
|
+ for variant in product.meta.inventory:
|
|
|
+ if variant.product_variation_id == product_variation_id:
|
|
|
+ is_available = variant.amount > 0
|
|
|
+ is_selectable = (variant.amount - quantity) > 0
|
|
|
+ amount = variant.amount
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ is_available = product.meta.inventory[0].amount > 0
|
|
|
+ is_selectable = (product.meta.inventory[0].amount - quantity) > 0
|
|
|
+ amount = product.meta.inventory[0].amount
|
|
|
|
|
|
- return (is_available, is_selectable, amount)
|
|
|
+ return is_available, is_selectable, amount
|
|
|
|
|
|
|
|
|
def update_product_inventory(
|
|
|
- filename: str, quantity: int, size: str, style: str, settings
|
|
|
+ filename: str,
|
|
|
+ quantity: int,
|
|
|
+ product_variation_id: str,
|
|
|
+ settings
|
|
|
) -> NoReturn:
|
|
|
"""Read given Product document and update its inventory amount based
|
|
|
on the given product's size and style. Afterwards write back
|
|
|
document to disk.
|
|
|
+
|
|
|
"""
|
|
|
doc = read_file(
|
|
|
settings.git_repo,
|
|
|
@@ -95,7 +87,7 @@ def update_product_inventory(
|
|
|
inventory = doc.meta.inventory
|
|
|
|
|
|
for model in inventory:
|
|
|
- if model.size == size and model.style == style:
|
|
|
+ if model.product_variation_id == product_variation_id:
|
|
|
# run extra check to see if what would be decreased
|
|
|
# would amount to at best 0 (eg. not going negative)
|
|
|
if model.amount - quantity >= 0:
|
|
|
@@ -115,6 +107,64 @@ def update_product_inventory(
|
|
|
git_add_commit(settings.git_repo, filepath, commit_msg)
|
|
|
|
|
|
|
|
|
+def create_variation_id(product: DocumentProduct):
|
|
|
+ """
|
|
|
+ Create a list of unique variation IDs mixing main product
|
|
|
+ id with size and style for variation for specified product
|
|
|
+ """
|
|
|
+
|
|
|
+ if len(product.meta.inventory) > 1:
|
|
|
+ variation_ids = []
|
|
|
+ for variant in product.meta.inventory:
|
|
|
+ if not variant.product_variation_id:
|
|
|
+ unique_variation_id = f"{product.meta.product_id}_"
|
|
|
+ if variant.size:
|
|
|
+ unique_variation_id += f"_{variant.size}"
|
|
|
+ if variant.style:
|
|
|
+ unique_variation_id += f"_{variant.style}"
|
|
|
+ variation_ids.append(unique_variation_id)
|
|
|
+ else:
|
|
|
+ variation_ids.append(None)
|
|
|
+ return variation_ids
|
|
|
+
|
|
|
+ return None # returns None in case there are no variations of the product or single variant only
|
|
|
+
|
|
|
+
|
|
|
+def write_variation_id(product:DocumentProduct, settings):
|
|
|
+ """ Generate and write IDs for variation of the product into file"""
|
|
|
+
|
|
|
+ filepath = f'{Path(settings.git_repo)}/{product.meta.path}/index.md'
|
|
|
+ product_file = parse_file(settings.git_repo, Path(filepath), settings.block_types)
|
|
|
+
|
|
|
+ ids = create_variation_id(product)
|
|
|
+
|
|
|
+ if ids:
|
|
|
+ for i in range(0, len(product.meta.inventory)):
|
|
|
+ if ids[i]:
|
|
|
+ product_file.meta.inventory[i].product_variation_id = ids[i]
|
|
|
+
|
|
|
+ txt_doc = convert_pydantic_product_to_text(product_file)
|
|
|
+ p = Path(filepath)
|
|
|
+
|
|
|
+ if p.exists():
|
|
|
+ with open(p, "w") as f:
|
|
|
+ f.write(txt_doc)
|
|
|
+
|
|
|
+ # update git repo
|
|
|
+ # commit_msg = "Update product inventory"
|
|
|
+ # git_add_commit(settings.git_repo, filepath, commit_msg)
|
|
|
+
|
|
|
+
|
|
|
+def get_variation_id(product:DocumentProduct, size: str | None, style: str | None) -> str | None:
|
|
|
+ """Returns variation ID for product that has size or style"""
|
|
|
+ if size or style:
|
|
|
+ for variant in product.meta.inventory:
|
|
|
+ if variant.size == size and variant.style == style:
|
|
|
+ return variant.product_variation_id
|
|
|
+
|
|
|
+ return None
|
|
|
+
|
|
|
+
|
|
|
def get_products_by_category(settings):
|
|
|
"""Helper function to product a list of products organized by their categories."""
|
|
|
products = read_dir(
|
|
|
@@ -225,9 +275,7 @@ def prepare_order_info(
|
|
|
if len(ci.keys()) > 0:
|
|
|
for k, v in ci.items():
|
|
|
for meta in products_meta:
|
|
|
- cart_product_id = create_product_id(
|
|
|
- meta.product_id, v.options.size, v.options.style
|
|
|
- )
|
|
|
+ cart_product_id = meta.product_id
|
|
|
|
|
|
if cart_product_id == k:
|
|
|
item = CartOrderInfo(
|