Skip to content

fix(web): batch offers read availability; radar and best offer skip sold-out listings - #1176

Merged
JOY (JOY) merged 2 commits into
devfrom
claude/web-1170-1171-1174-offer-availability
Oct 28, 2026
Merged

JOY (JOY) merged 2 commits into
devfrom
claude/web-1170-1171-1174-offer-availability

Conversation

@JOY

@JOY JOY (JOY) commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #1141 / #1164: sold-out and discontinued listings no longer show up as deals or best offers anywhere. One PR for all three issues, since the diff is small and they touch the same read.

Changes

Tests

  • New block 126k in core-rate-architecture.test.ts covers:
    • the batch read attaches availability, on both the view and fallback paths;
    • a failed availability read fails the single and batch reads;
    • the radar never cites sold-out or discontinued offers (Buds3 Pro shape);
    • stock: 0 + in_stock stays buyable, and out_of_stock / discontinued are skipped.
  • The fix(web): resolve specifications.category_slug and harden merchant/stats category & review trust mapping #513 merchant profile mock matched cluster_id=in. as id=in.. It is narrowed so the new .in('cluster_id', …) read gets an empty page.
  • Local: pnpm --filter @repo/web test, tsc --noEmit and eslint on the changed files are green.

Runtime check after deploy

Buds3 Pro's watchlist entry should get a best offer of 3,140,000 from an in-stock seller (#1171 acceptance), and the earbuds category radar should not cite FPT Shop's 2,694,000.

Closes #1170
Closes #1171
Closes #1174

🤖 Generated with Claude Code


📌 TL;DR

Refactors the listing availability lookup to support batch processing and strict error handling, while updating the deal radar and best-offer selection logic to exclude sold-out or discontinued listings based on the availability field rather than the unreliable stock count.

🎯 Type of Change

  • 🚀 New feature
  • 🐛 Bugfix
  • 🧹 Refactor
  • ⚡ Performance
  • 📚 Documentation
  • ⚙️ CI / Configuration

🔍 Changes Walkthrough

File Summary of Changes
apps/web/src/lib/rate-api.ts Refactored getListingAvailabilityForMaster into getListingAvailability to accept an array of master IDs. Replaced manual pagination and silent error swallowing with the shared fetchAllRows utility, ensuring that availability read failures now throw RateDataUnavailableError instead of returning an empty map. Updated getMasterProductOffersBatch to fetch availability in parallel with offer data and apply it to results.
apps/web/src/server/rate/api-handler.ts Updated selectBestOfferFromListings to filter out unavailable offers using isOfferUnavailable before price validation. Removed the stock > 0 check, as stock: 0 is now treated as "unknown" rather than "out of stock," relying solely on the availability status. Added availability to the WatchlistCandidateOffer interface.
apps/web/src/server/rate/deals.ts Modified computeCrossPlatformDealRadarFromData to exclude sold-out or discontinued listings from the valid offers pool. This prevents unavailable items from skewing price spreads, deal signals, or trap detection metrics.
apps/web/src/server/rate/__tests__/core-rate-architecture.test.ts Added comprehensive test suite (126k) verifying that batch availability reads work correctly, that failed availability reads cause the entire offer fetch to fail, and that the radar/best-offer logic correctly ignores sold-out items while treating stock: 0 with unknown availability as valid.

📊 Architectural Flow

sequenceDiagram
    participant Client
    participant APIHandler as api-handler.ts
    participant RateAPI as rate-api.ts
    participant DB as Supabase (rate.products)
    participant Deals as deals.ts

    Client->>APIHandler: Request Offers (Batch)
    APIHandler->>RateAPI: getMasterProductOffersBatch(masterIds)
    
    par Fetch Offers
        RateAPI->>DB: Select from v_products_with_merchant_trust
        DB-->>RateAPI: Offer Rows
    and Fetch Availability
        RateAPI->>DB: Select id, availability from products (IN masterIds)
        DB-->>RateAPI: Availability Rows
    end
    
    Note over RateAPI: If Availability Read Fails, Throw RateDataUnavailableError
    
    RateAPI->>RateAPI: Map offers with availability status
    RateAPI-->>APIHandler: Offers with Availability
    
    APIHandler->>APIHandler: selectBestOfferFromListings
    Note right of APIHandler: Filters out isOfferUnavailable<br/>(ignores stock count)
    
    APIHandler->>Deals: computeCrossPlatformDealRadarFromData
    Note right of Deals: Filters out isOfferUnavailable<br/>before calculating spreads
    Deals-->>APIHandler: Radar Data
    APIHandler-->>Client: Response
Loading

…old-out listings

- getMasterProductOffersBatch reads rate.products.availability per chunk and
  attaches it, like the single-product read (#1170).
- The deal radar drops out_of_stock and discontinued offers before the market
  floor, spread, deals and traps, for every caller (#1170).
- selectBestOfferFromListings decides on availability, not stock: crawlers
  report stock 0 when they read no count (#1171).
- The availability read no longer falls back to unknown on a failed read or a
  missing column; it throws RateDataUnavailableError like the offer reads
  (#1174).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@vercel

vercel Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
rate Ready Ready Preview Oct 28, 2026 4:17am UTC

Request Review

@github-actions github-actions Bot added the area:frontend Frontend / Next.js / UI label Oct 28, 2026
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 48 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b1e5d2ce-163c-414a-9343-b9e635c47de3
Commits

Reviewing files that changed from the base of the PR and between 20809d6 and 7ccd4ec.

Files selected for processing: 4
  • apps/web/src/lib/rate-api.ts
  • apps/web/src/server/rate/__tests__/core-rate-architecture.test.ts
  • apps/web/src/server/rate/api-handler.ts
  • apps/web/src/server/rate/deals.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

dos[bot]
dos Bot approved these changes Oct 28, 2026

@dos dos Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⏱️ Code Review completed (4 eligible files · 19,279 chars · 2 model call(s) · 1 PR unit(s))

Whole diff with bounded context at base 80eaded / head 4a7686d.

✅ CLEAN_PASS: Complete diff reviewed

Context investigation was bounded to the explicitly requested snapshot paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dos[bot]
dos Bot approved these changes Oct 28, 2026

@dos dos Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⏱️ Code Review completed (4 eligible files · 19,363 chars · 2 model call(s) · 1 PR unit(s))

Whole diff with bounded context at base 80eaded / head 7ccd4ec.

✅ CLEAN_PASS: Complete diff reviewed

Context investigation was bounded to the explicitly requested snapshot paths.

@JOY
JOY (JOY) merged commit c135412 into dev Oct 28, 2026
14 checks passed
@JOY
JOY (JOY) deleted the claude/web-1170-1171-1174-offer-availability branch October 28, 2026 04:23

This branch was successfully deployed

1 active deployment
Preview — 7ccd4ecb Deployed Oct 28, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:frontend Frontend / Next.js / UI

Projects

None yet

1 participant