The Netorigo Storefront cart is not always a cart. The moment any cart line carries CartLine.isOnlinePurchasable=false, the cart flips into RFQ (Request for Quote) mode. This article covers the design decisions, plus 18 months of live data across four storefronts.
The flag: isOnlinePurchasable
The product Prisma table has a boolean isOnlinePurchasable. When false, the PDP shows no "Add to cart" button — only an "Request quote" CTA. If someone forces it into a cart anyway (e.g., as part of a bundle, or via admin override), the cart line renders with an amber (--nrt-amber-500) "Quote-based" badge.
The flag is toggled in the admin at /admin/catalog/products/[id]. The default is true because the Storefront is primarily B2C; only industrial / project-grade items go RFQ.
Mode switching: the checkout itself
The moment at least one quote-only line is in the cart, the useCartPurchasability(items) hook returns a mode: 'quote' or mode: 'mixed' discriminator. The /checkout page branches on it:
mode: 'cart': classic payment checkout (Barion, Stripe, bank transfer).mode: 'quote': RFQ form. Fields: company name, VAT number, purchasing contact name + phone, free-text note. Submit routes through thesubmitQuoteRequestMCP tool to the backend'squotes.createendpoint, which inserts a row intoquote_requestand notifies the sales-rep module.mode: 'mixed': dual checkout. Purchasable lines go straight to payment, quote-only lines go to RFQ. The buyer receives two emails (order confirmation + quote request acknowledgement).
The mixed case is tricky. We had a long design debate: do we let the buyer split workflows, or force them to choose ("everything as RFQ" / "just the purchasable lines now")? The split workflow won, because most partner sales teams asked for it — "do not stall an online purchase on a long RFQ cycle."
The sales hand-over
The quote lands in the /admin/sales/quotes module. The module lists, ranks them by priority + value, and the sales rep authors a quote response there (PDF generated from the quote). The response comes back to the buyer carrying a 14-day-expiring quote-specific-pricing cookie: opening the quote URL shows the negotiated price (not the list price), so the buyer can self-serve completion.
18 months of numbers (n=1,247 quotes, 4 storefronts)
- Total quotes: 1,247 (avg 69/month, November peak of 142)
- PO conversion: 34% (424 completed orders)
- Median quote-to-PO: 8 days (mean 11.4, p90 21)
- Self-serve completion via the quote URL: 11% of POs (47 cases, only accurately measured since March 2025)
- Average quote value: 1.2M HUF; average PO value from quote: 980k HUF (so the buyer-negotiated discount averages ~18%)
- Expired quotes (14 days): 23% (the rest either flow into a new quote or quietly die)
The downside nobody talks about
The quote-first cart visibly degrades the cart-conversion metric (the classic "adds-to-cart / completes purchase" funnel), because you lose a cohort: the quote requesters. Do not measure the quote-driven revenue with the same KPI — the 8-day lag spreads the money out of the metric window. Run two parallel measurement tracks: the quote pipeline on the sales side, the cart conversion on the marketing side. Don't mix.