Wholesale Section Development for E-Commerce in 1C-Bitrix
A wholesale section within a retail store is not a separate website, but parallel business logic for authorized B2B clients. One catalog, one admin panel, but different prices, order rules, and documentation workflow. In Bitrix, this task is solved via price types, user groups, and refinements to the sale module.
Price Types and Access Rights: B2B Foundation
All B2B price architecture is built around the b_catalog_group table. Each record is a separate price type: "Retail", "Wholesale", "Dealer", "VIP". Binding of price type to user group is set in catalog module settings — section "Price Types", column "Buyer Groups".
The mechanism works like this:
- User logs in and is placed in a group (e.g., "Wholesalers")
- Catalog component calls
CCatalogProduct::GetOptimalPrice(), which iterates through available price types for current user - Returns the smallest of available prices (or highest priority price — depends on setting)
In practice, one price type mechanism is insufficient. Real wholesale price lists are more complex:
-
Individual discounts — contractor A gets 12% discount, contractor B — 18%. Solution: separate user group for each major contractor with their own price type, or cart rules (
sale.discount) with group condition. -
Threshold prices — buying from 100 units costs one price, from 1000 — another. In standard Bitrix, this is implemented via quantity ranges in product prices (
b_catalog_pricesupportsQUANTITY_FROM/QUANTITY_TO). -
Multi-currency prices — wholesale clients from different countries see prices in their currency. Price types can be set in different currencies, conversion — via
currencymodule.
Important nuance: price type is not directly bound to user — only to group. If individual pricing is needed for 200 contractors, creating 200 groups is impractical. In such cases, an OnGetOptimalPrice event handler is written, which pulls price from external source (1C, ERP) via cache.
| Scenario | Bitrix Implementation | Limitations |
|---|---|---|
| 3–5 price levels | Price types + user groups | Standard mechanism, works out of box |
| Threshold prices by quantity | Ranges in b_catalog_price |
Not displayed in card without template refinement |
| Individual contractor pricing | OnGetOptimalPrice event + external source |
Requires caching, otherwise — request to 1C per product |
| Category discount for group | Cart rules sale.discount |
Not visible in catalog until cart addition |
Minimum Order Quantity and Order Increment
For wholesale products, two parameters are needed: minimum order quantity and increment (step). Standard Bitrix has "Unit of Measure Coefficient" field (b_catalog_measure_ratio), but it only works as multiplier when adding to cart.
Full implementation requires:
- Iblock property "Minimum Order Quantity" — checked when adding to cart via
OnSaleBasketItemBeforeUpdatehandler - "Order Increment" property — quantity is rounded up to nearest increment value
- Display in product card — instead of standard quantity field, show selector with steps (10, 20, 30…) or field with validation
Quick Order by Article Number and Excel Upload
Wholesale client doesn't browse catalog — they know article numbers. Need quick order interface:
-
"Article + Quantity" form — row list where data is entered. Server-side article matches
PROPERTY_CML2_ARTICLEorXML_IDof iblock element, product is added to cart. -
Excel/CSV upload — client exports file from their accounting system. Parser on Bitrix side (PhpSpreadsheet library, connected via Composer) parses file, finds products, forms cart. Unmatched articles shown in report.
-
Repeat previous order — button in personal area copying previous order composition to current cart. Implemented via
Bitrix\Sale\Basket::loadItemsForOrder().
Credit Limits and Deferred Payment
In B2B, payment often happens after the fact. Credit limit mechanism:
- In contractor profile (extended user properties or
UF_*fields) limit and current debt are stored - When placing order,
OnSaleOrderBeforeSavedhandler checks: order sum + current debt ≤ credit limit - If limit exceeded — order not placed, user sees message with available remainder
- After payment (payment status change via 1C exchange or manually) debt is recalculated
Document Management in Personal Area
Wholesale client expects to see in personal area:
-
Invoices — generated automatically on order creation. PDF template assembled via print handler (
sale_print) or external library (TCPDF/mPDF). - Reconciliation acts — pulled from 1C via exchange. Stored as files bound to user via highload-block.
- Delivery notes and UPD — likewise, exported from 1C. For legal validity can be signed with e-signature.
-
Order history with filtering — by period, status, amount. Standard
sale.personal.ordercomponent is refined or replaced with custom.
Separate Cart and Context Separation
Technically in Bitrix there's one cart per user. If client can buy both retail and wholesale, separation is needed:
-
Option 1: Site type. Two sites in one Bitrix installation — retail and wholesale. Carts separated by
FUSER_ID+LID(site identifier). Downside — settings duplication. -
Option 2: Custom basket item property. Add custom property
BASKET_TYPE=wholesale. At checkout, only wholesale items are filtered. Downside — more complex to implement, needs template refinement.
In practice, first option is more reliable: two sites with shared catalog, different templates, independent carts. Switching between "windows" — via subdomain or URL section.
Integration with 1C for Wholesale Section
Exchange with 1C for B2B section includes additional entities absent in standard CommerceML:
- Contractors — synchronization of contractor cards from 1C with Bitrix user profiles. Mapping by INN or XML_ID.
- Accounts receivable — current debt, payments, credit limit. Transmitted via additional XML nodes or separate REST request.
- Individual price lists — if kept in 1C, need export mechanism in format "contractor → product → price". Standard exchange doesn't support this — separate exchange script is written.
Wholesale section always requires customization, not out-of-box configuration. Work volume depends on integration depth with accounting system and document workflow requirements.







