AuthorBot Cursor commited on
Commit
ecd655e
·
1 Parent(s): afad341

fix: don't collapse Amazon/BN format prices to single eBook label when credential set

Browse files

Credentialed price fetch previously short-circuited before the multi-format
HTML parser and mislabeled every price as eBook. Now Amazon/Barnes & Noble
always attempt the full format-swatch parse first (Hardcover/eBook/Audiobook),
with the credential single price only as a fallback. Also stop guessing an
eBook binding for print/mixed retailers on the credential path.

Co-authored-by: Cursor <cursoragent@cursor.com>

Files changed (1) hide show
  1. app/services/platform_pricing.py +35 -2
app/services/platform_pricing.py CHANGED
@@ -467,11 +467,20 @@ async def fetch_listing_format_prices(
467
  return await _fetch_apple_format_prices(client, listing_url, ctx)
468
 
469
  # --- Credential-based platforms ---
470
- if credential is not None:
 
 
 
 
 
471
  from app.services.platform_api_registry import fetch_price_via_credential
472
  hit = await fetch_price_via_credential(client, credential, platform_id, listing_url, ctx)
473
  if hit:
474
- norm = canonical_format_prices({"eBook": hit.formatted}, platform_id)
 
 
 
 
475
  return FormatPriceHit(
476
  format_prices=norm,
477
  formatted=hit.formatted,
@@ -536,9 +545,33 @@ async def fetch_listing_format_prices(
536
  platform=platform_id,
537
  error=str(exc)[:120],
538
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  return None
540
 
541
 
 
 
 
 
 
 
 
 
542
  def _itunes_price_from_item(item: dict) -> tuple[str, str] | None:
543
  """Return (formatted_price, currency) from an iTunes lookup/search item."""
544
  raw_price = item.get("formattedPrice")
 
467
  return await _fetch_apple_format_prices(client, listing_url, ctx)
468
 
469
  # --- Credential-based platforms ---
470
+ # Amazon / Barnes & Noble expose ALL formats on their product page, so we
471
+ # skip the single-price credential shortcut for them and let the HTML
472
+ # multi-format parser run below. Only use credential fetch as a fallback
473
+ # (handled after the HTML attempt) so we never collapse 3 formats into 1.
474
+ _MULTI_FORMAT_HTML = {"amazon", "barnes_noble"}
475
+ if credential is not None and platform_id not in _MULTI_FORMAT_HTML:
476
  from app.services.platform_api_registry import fetch_price_via_credential
477
  hit = await fetch_price_via_credential(client, credential, platform_id, listing_url, ctx)
478
  if hit:
479
+ fmt_key = _single_price_credential_format(platform_id)
480
+ norm = (
481
+ canonical_format_prices({fmt_key: hit.formatted}, platform_id)
482
+ if fmt_key else {}
483
+ )
484
  return FormatPriceHit(
485
  format_prices=norm,
486
  formatted=hit.formatted,
 
545
  platform=platform_id,
546
  error=str(exc)[:120],
547
  )
548
+
549
+ # Amazon / BN HTML gave nothing (e.g. bot wall) — fall back to credential fetch.
550
+ if credential is not None and platform_id in _MULTI_FORMAT_HTML:
551
+ from app.services.platform_api_registry import fetch_price_via_credential
552
+ hit = await fetch_price_via_credential(client, credential, platform_id, listing_url, ctx)
553
+ if hit:
554
+ fmt_key = _single_price_credential_format(platform_id)
555
+ norm = (
556
+ canonical_format_prices({fmt_key: hit.formatted}, platform_id)
557
+ if fmt_key else {}
558
+ )
559
+ return FormatPriceHit(
560
+ format_prices=norm,
561
+ formatted=hit.formatted,
562
+ currency=hit.currency,
563
+ )
564
  return None
565
 
566
 
567
+ def _single_price_credential_format(platform_id: str) -> str:
568
+ """Best-effort format label for a single credential price (empty if unknown)."""
569
+ if platform_id in {"kobo", "google_books"}:
570
+ return "eBook"
571
+ # Print-focused / mixed retailers: don't guess a binding.
572
+ return ""
573
+
574
+
575
  def _itunes_price_from_item(item: dict) -> tuple[str, str] | None:
576
  """Return (formatted_price, currency) from an iTunes lookup/search item."""
577
  raw_price = item.get("formattedPrice")