Oakhammer B2B for WooCommerce
Documentation · Free, Pro and Business
Sell to retail and trade customers from one WooCommerce store. Wholesale customers log in and see their prices everywhere: product pages, cart, checkout, emails. Everyone else sees your normal prices.
Getting started
- Install WooCommerce, then upload and activate Oakhammer B2B.
- WooCommerce → Settings → B2B: choose whether guests see prices, and set a wholesale minimum order if you want one.
- Users → edit a customer → Role: Wholesale customer.
- Products → edit → B2B tab: pick Fixed price or % off retail for the Wholesale role. The last column shows the price that role pays now and the margin.
Variations without their own rule use the product's rule. Set a variation rule on the Variations tab.
Hide prices from guests
Turn on Hide prices from guests. Visitors who aren't logged in see "Log in to see prices" (change the text in settings) and can't add to cart. Prices are also removed from the Store API and from product structured data.
Wholesale minimum order
Wholesale customers can't check out until their cart subtotal (before tax and shipping) reaches the minimum. Works in the classic and block cart and checkout. Retail customers are never affected.
Sales
A B2B customer never pays more than a retail customer pays right now. If a product is on sale for less than the wholesale price, the wholesale customer gets the sale price. (Developers: filter ohb2b_cap_at_retail.)
Where costs come from
Each product's B2B tab shows its cost and where it came from, e.g. Cost $182.40 · from BOM Pricing. B2B looks in this order:
- Another Oakhammer plugin that supplies a cost (filter
oakhammer_product_cost). - Oakhammer BOM Pricing, when it's active: the rolled-up cost of a kit, or a part's unit cost.
- WooCommerce cost of goods, when you've turned that feature on.
- The Cost field on the B2B tab (only shown when none of the above has a cost).
No cost? Cost-based rules are skipped (fixed and % off still work) and margins show "no cost — margin not checked".
Works with BOM Pricing
B2B works on its own. With Oakhammer BOM Pricing active:
- Cost-based wholesale prices use BOM Pricing's kit costs.
- When a component cost changes, every kit that uses it, and every wholesale price built on it, updates by itself.
- Quotes keep the cost from the moment the line was added, so a later component change never alters a quote you've sent.
- If you deactivate BOM Pricing, B2B falls back to the next cost source without errors, and returns to BOM costs when you reactivate it.
Pro Pro
Roles
WooCommerce → B2B → Roles & pricing. Add roles such as Dealer or Distributor. Each role has:
- Default rule: used when the variation, product and category have none.
- Margin floor (% over cost): the price is never below cost × (1 + floor). 25 means at least 25% over cost.
- Quantity breaks:
10:5, 25:10means 5% off at 10+ and 10% off at 25+ on a cart line. - Minimum order: overrides the store minimum for this role.
Cost-based pricing
Two more rule types: Cost + markup % and Cost + fixed amount. Use them on a variation, product, category (Products → Categories → edit), role, or as the store default (Settings → B2B → Pricing).
Which rule wins
Most specific first: variation → product → category → role → store default. Then the quantity break, then the margin floor raises the price if needed.
| Step | Example | Result |
|---|---|---|
| Rule (product, Dealer) | cost + 25% on $182.40 | $228.00 |
| Quantity break | 10+ in cart, 5% off | $216.60 |
| Margin floor | Dealer floor 20% → min $218.88 | $218.88 |
| Cap at retail | Retail is $299.99 | $218.88 |
Dealer applications
Put [ohb2b_dealer_application] on a page. Applications wait under WooCommerce → B2B → Applications. Approve (pick the role) or reject (optional reason). The applicant is emailed either way; new applicants get a link to set their password.
Tax-exempt customers
On the customer's profile, tick Tax exempt and enter their Tax ID. They pay no tax in the classic or block checkout, and the tax ID is saved on their orders.
Business Business
Quotes
Customers click Request a quote on a product page or in the cart. You get an email; open the quote in WooCommerce → Quotes.
The quote builder shows cost, price, margin % and margin $ for every line and in total, with a warning on any line below the role's margin floor. Change prices and quantities, add or remove products, set Valid until, and Send. The customer gets an email with a PDF and a link. In My Account → Quotes they can Accept, which creates an order at the quoted prices, ready to pay, or decline.
- Expired quotes can't be accepted. Re-send with a new date.
- Changing a quote after sending puts it back to draft until you send it again.
- A quote can only be accepted once, even from two browser tabs.
- Statuses: requested, draft, sent, accepted, declined, expired, converted (order placed).
Net terms
WooCommerce → Settings → Payments → Net terms (B2B). On a customer's profile, choose Net 15 / 30 / 60 and an optional allowance. Only those B2B customers see the method; orders go on hold with a due date. When the invoice is paid, use the order action Mark net terms invoice paid to free their allowance.
WP-CLI
wp ohb2b price <product-id> --customer=<email> [--qty=10]
wp ohb2b cost <product-id>
wp ohb2b set-rule <product-id> --role=ohb2b_wholesale --type=fixed --value=450
wp ohb2b set-cost <product-id> --value=182.40
wp ohb2b quote list [--status=sent] [--format=csv]
wp ohb2b quote export > quotes.csv
Removing the plugin
Your data is kept unless you tick Remove data on delete (Settings → B2B) or define OHB2B_REMOVE_ALL_DATA as true. Then deleting the plugin removes its settings, wholesale prices, B2B costs, customer B2B details and quotes. B2B customers become regular customers. Orders are never changed.
FAQ
Which price does "% off retail" start from?
The regular price (or the price, when there is no regular price).
Does it work with the block cart and checkout?
Yes. The same prices appear in the classic and block cart and checkout, the mini-cart and the Store API.
Does it work with HPOS?
Yes. Quotes live in their own tables and don't depend on order storage. The test suite runs with HPOS off and on.
Can a customer have more than one B2B role?
A customer's B2B price comes from their B2B role. Give each customer one B2B role.
A tax-exempt customer is still being charged tax.
Check the customer is logged in and the Tax exempt box is ticked on their profile. If you've just changed it, have them reload the cart so the session picks it up.
Developers
| Hook | What it does |
|---|---|
oakhammer_product_cost | Filter. Supply a cost for a product ID before B2B looks at BOM Pricing, Woo COGS or its own field. |
ohb2b_cap_at_retail | Filter. Return false to let a B2B price exceed the current retail (sale) price. |
ohb2b_get_cost( $product_id ) | Function. The resolved cost and its source. |
ohbp_*_cost_changed | B2B listens to BOM Pricing's cost-change actions and bumps its price cache generation. |
Prefix: ohb2b. Tables: ohb2b_quotes, ohb2b_quote_lines. Prices are calculated on the server; cart lines are priced per quantity and locked so recalculation never compounds.