update torob api
This commit is contained in:
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import math
|
||||
from urllib.parse import urlparse
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
import jwt
|
||||
from django.conf import settings
|
||||
@@ -80,6 +80,18 @@ def _extract_slug_from_url(value: str) -> str | None:
|
||||
return path.split("/")[-1]
|
||||
|
||||
|
||||
def _extract_variant_id_from_url(value: str) -> str | None:
|
||||
query = urlparse(value).query
|
||||
if not query:
|
||||
return None
|
||||
params = parse_qs(query)
|
||||
variant_values = params.get("variant") or []
|
||||
if not variant_values:
|
||||
return None
|
||||
candidate = variant_values[0].strip()
|
||||
return candidate or None
|
||||
|
||||
|
||||
def _variant_page_unique(product: ProductModel, variant: ProductVariant) -> str:
|
||||
return f"{product.pk}_{variant.pk}"
|
||||
|
||||
@@ -109,13 +121,15 @@ def _absolute_url(request, value: str) -> str:
|
||||
return request.build_absolute_uri(value)
|
||||
|
||||
|
||||
def _shop_product_url(request, product: ProductModel) -> str:
|
||||
def _shop_product_url(request, product: ProductModel, variant: ProductVariant | None = None) -> str:
|
||||
domain = getattr(settings, "DOMAIN", None) or getattr(settings, "API_DOMAIN", None) or request.get_host()
|
||||
if domain.startswith("http://") or domain.startswith("https://"):
|
||||
base = domain.rstrip("/")
|
||||
else:
|
||||
base = f"https://{domain}".rstrip("/")
|
||||
url = f"{base}/product/{product.slug}/"
|
||||
if variant is not None:
|
||||
url = f"{url}?variant={variant.pk}"
|
||||
# Per spec: page_url max 1500 chars
|
||||
return url[:1500]
|
||||
|
||||
@@ -140,9 +154,6 @@ def _variant_spec(variant: ProductVariant | None) -> dict:
|
||||
if variant.color:
|
||||
spec.setdefault("color", variant.color)
|
||||
|
||||
if variant.in_stock is not None:
|
||||
spec.setdefault("in_stock", variant.in_stock)
|
||||
|
||||
return spec
|
||||
|
||||
|
||||
@@ -213,7 +224,7 @@ def _serialize_variant(request, product: ProductModel, variant: ProductVariant)
|
||||
|
||||
payload = {
|
||||
"page_unique": _variant_page_unique(product, variant),
|
||||
"page_url": _shop_product_url(request, product),
|
||||
"page_url": _shop_product_url(request, product, variant),
|
||||
"product_group_id": str(product.pk),
|
||||
"title": _truncate_text(product.name, 500),
|
||||
"subtitle": _truncate_text(product.meta_description, 500),
|
||||
@@ -222,11 +233,11 @@ def _serialize_variant(request, product: ProductModel, variant: ProductVariant)
|
||||
"category_name": _truncate_text(product.category.name if product.category else None, 200),
|
||||
"image_links": _product_image_links(request, product, variant),
|
||||
"spec": _variant_spec(variant),
|
||||
"guarantee": None,
|
||||
"guarantee": _truncate_text(variant.guarantee, 200),
|
||||
"short_desc": _truncate_text(product.description, 500),
|
||||
"date_added": _variant_date_added(product, variant),
|
||||
"date_updated": _variant_date_updated(product, variant),
|
||||
"seller_name": product.shop.shop_name if product.shop else None,
|
||||
# "seller_name": product.shop.shop_name if product.shop else None,
|
||||
}
|
||||
|
||||
if old_price is not None and old_price > current_price:
|
||||
@@ -336,27 +347,49 @@ class TorobProductSyncView(APIView):
|
||||
for product in products
|
||||
}
|
||||
|
||||
ordered_products = []
|
||||
ordered_lookups: list[tuple[ProductModel, str | None]] = []
|
||||
for url in requested_urls:
|
||||
slug = _extract_slug_from_url(url)
|
||||
normalized_url = _normalize_url(url)
|
||||
variant_id = _extract_variant_id_from_url(url)
|
||||
product = product_by_slug.get(slug) if slug else None
|
||||
if product is None:
|
||||
product = product_by_url.get(normalized_url)
|
||||
if product is not None and product not in ordered_products:
|
||||
ordered_products.append(product)
|
||||
if product is None:
|
||||
continue
|
||||
ordered_lookups.append((product, variant_id))
|
||||
|
||||
serialized_products = []
|
||||
for product in ordered_products:
|
||||
seen: set[str] = set()
|
||||
for product, variant_id in ordered_lookups:
|
||||
variants = list(product.variants.all())
|
||||
if not variants:
|
||||
continue
|
||||
|
||||
if variant_id:
|
||||
variant = next((v for v in variants if str(v.pk) == variant_id), None)
|
||||
if not variant:
|
||||
continue
|
||||
image_links = _product_image_links(request, product, variant)
|
||||
if not image_links:
|
||||
continue
|
||||
page_unique = _variant_page_unique(product, variant)
|
||||
if page_unique in seen:
|
||||
continue
|
||||
seen.add(page_unique)
|
||||
serialized_products.append(_serialize_variant(request, product, variant))
|
||||
continue
|
||||
|
||||
variants.sort(key=_variant_sort_key)
|
||||
for variant in variants:
|
||||
image_links = _product_image_links(request, product, variant)
|
||||
# Skip variants without images as per spec requirement
|
||||
if not image_links:
|
||||
continue
|
||||
page_unique = _variant_page_unique(product, variant)
|
||||
if page_unique in seen:
|
||||
continue
|
||||
seen.add(page_unique)
|
||||
serialized_products.append(_serialize_variant(request, product, variant))
|
||||
|
||||
return Response(
|
||||
|
||||
Reference in New Issue
Block a user