mirror of
https://github.com/nethunterzist/trendyol-analiz
synced 2026-07-01 17:37:04 +00:00
fix: 0 ürünlü kategori 500 hatası + satıcı bilgileri eklendi
Ne yaptık: - build_consolidated_report(): normalized_products boş olunca None yerine empty=true içeren boş dashboard döndürüyor - normalize_product(): seller_count, has_buybox, is_trendyol_product alanları eklendi - Social proof: metrik bazında en doğru kaynak seçimi (inline vs enrichment API) Neden yaptık: - Boş kategorilerde dashboard-data endpoint 500 fırlatıyordu, kullanıcı loading skeleton'dan çıkamıyordu - Satıcı sayısı ve buybox bilgisi Ürünler tablosu için gerekli Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -177,39 +177,43 @@ def normalize_product(raw_product, category_name, social_details):
|
||||
brand = raw_product.get("brand", {})
|
||||
brand_name = (brand.get("name") if isinstance(brand, dict) else brand) or "Bilinmeyen"
|
||||
|
||||
# ── Social proof: önce inline socialProofs, sonra enrichment ──
|
||||
# ── Social proof: metrik bazında en doğru kaynağı seç ──
|
||||
orders, page_views, baskets, favorites = 0, 0, 0, 0
|
||||
|
||||
# İnline socialProofs (Top Rankings API — ürün dosyasında kayıtlı)
|
||||
# 1. Inline socialProofs (Top Rankings API) — sipariş için kesin sayı verir
|
||||
inline_orders, inline_views, inline_baskets, inline_favorites = 0, 0, 0, 0
|
||||
social_proofs = raw_product.get("socialProofs", [])
|
||||
if isinstance(social_proofs, list):
|
||||
for proof in social_proofs:
|
||||
proof_type = proof.get("type", "")
|
||||
parsed = _parse_social_value(proof.get("value", "0"))
|
||||
if proof_type == "orderCountL3D":
|
||||
orders = parsed
|
||||
inline_orders = parsed
|
||||
elif proof_type == "pageViewCount":
|
||||
page_views = parsed
|
||||
inline_views = parsed
|
||||
elif proof_type == "basketCount":
|
||||
baskets = parsed
|
||||
inline_baskets = parsed
|
||||
elif proof_type == "favoriteCount":
|
||||
favorites = parsed
|
||||
inline_favorites = parsed
|
||||
|
||||
# Enrichment API (social.json) — inline yoksa veya 0 ise fallback
|
||||
# Key hem str hem int olabilir (dosyadan str, memory'den int)
|
||||
# 2. Enrichment API (social.json) — görüntülenme/sepet/favori için daha doğru
|
||||
sp = {}
|
||||
if product_id and social_details:
|
||||
sp = (social_details.get(str(product_id))
|
||||
or social_details.get(int(product_id) if str(product_id).isdigit() else -1)
|
||||
or {})
|
||||
if not orders:
|
||||
orders = sp.get("orders", 0) or 0
|
||||
if not page_views:
|
||||
page_views = sp.get("page_views", 0) or 0
|
||||
if not baskets:
|
||||
baskets = sp.get("baskets", 0) or 0
|
||||
if not favorites:
|
||||
favorites = sp.get("favorites", 0) or 0
|
||||
enrich_orders = sp.get("orders", 0) or 0
|
||||
enrich_views = sp.get("page_views", 0) or 0
|
||||
enrich_baskets = sp.get("baskets", 0) or 0
|
||||
enrich_favorites = sp.get("favorites", 0) or 0
|
||||
|
||||
# 3. Metrik bazında en doğru kaynağı seç:
|
||||
# - Sipariş: Top Rankings kesin sayı verir (294), SP API yuvarlar (500+)
|
||||
# - Diğerleri: SP API daha kesin (17.8B=17800), Top Rankings yuvarlar (3k=3000)
|
||||
orders = inline_orders or enrich_orders
|
||||
page_views = enrich_views or inline_views
|
||||
baskets = enrich_baskets or inline_baskets
|
||||
favorites = enrich_favorites or inline_favorites
|
||||
|
||||
# ── Image URL ──
|
||||
image_url = raw_product.get("imageUrl", "")
|
||||
@@ -221,6 +225,8 @@ def normalize_product(raw_product, category_name, social_details):
|
||||
product_url = raw_product.get("url", "")
|
||||
if not product_url and product_id:
|
||||
product_url = f"https://www.trendyol.com/p/{product_id}"
|
||||
elif product_url and not product_url.startswith("http"):
|
||||
product_url = f"https://www.trendyol.com{product_url}" if product_url.startswith("/") else f"https://www.trendyol.com/{product_url}"
|
||||
|
||||
# ── Barcode ──
|
||||
barcode = ""
|
||||
@@ -242,6 +248,11 @@ def normalize_product(raw_product, category_name, social_details):
|
||||
)
|
||||
break
|
||||
|
||||
# ── Satıcı bilgileri ──
|
||||
seller_count = len(merchant_listings)
|
||||
has_buybox = merchant_listings[0].get("isWinner", False) if merchant_listings else False
|
||||
is_trendyol_product = barcode.startswith(("TYB", "SGT", "KPE", "RTN", "CDM")) if barcode else False
|
||||
|
||||
return {
|
||||
"id": product_id,
|
||||
"name": raw_product.get("name", ""),
|
||||
@@ -261,6 +272,9 @@ def normalize_product(raw_product, category_name, social_details):
|
||||
"image_url": image_url or "https://via.placeholder.com/150",
|
||||
"url": product_url,
|
||||
"in_stock": raw_product.get("inStock", False),
|
||||
"seller_count": seller_count,
|
||||
"has_buybox": has_buybox,
|
||||
"is_trendyol_product": is_trendyol_product,
|
||||
}
|
||||
|
||||
|
||||
@@ -732,8 +746,25 @@ def build_consolidated_report(report_id, db, reports_dir, social_data=None):
|
||||
continue
|
||||
|
||||
if not normalized_products:
|
||||
log.warning(f"Rapor {report_id} için ürün bulunamadı")
|
||||
return None
|
||||
log.warning(f"Rapor {report_id} için ürün bulunamadı — boş dashboard döndürülüyor")
|
||||
return {
|
||||
"metadata": {
|
||||
"report_id": report_id,
|
||||
"report_name": report.name,
|
||||
"created_at": report.created_at.isoformat() if report.created_at else None,
|
||||
"total_products": 0,
|
||||
"total_categories": 0,
|
||||
"consolidated_at": datetime.now().isoformat(),
|
||||
"empty": True,
|
||||
},
|
||||
"report_id": report_id,
|
||||
"report_name": report.name,
|
||||
"products": [],
|
||||
"all_products": [],
|
||||
"kpis": calculate_kpis([]),
|
||||
"charts": calculate_charts([]),
|
||||
"insights": calculate_insights([]),
|
||||
}
|
||||
|
||||
# ── Hesaplamalar ──
|
||||
kpis = calculate_kpis(normalized_products)
|
||||
|
||||
Reference in New Issue
Block a user