From 2b1c2b72c13fdab960f086c2b02815a3d978bcc4 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Thu, 28 May 2026 10:33:07 +0330 Subject: [PATCH] update torob api --- backend/product/torob_api.py | 57 ++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/backend/product/torob_api.py b/backend/product/torob_api.py index 28d2527..583581b 100644 --- a/backend/product/torob_api.py +++ b/backend/product/torob_api.py @@ -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(