The B2B Commerce Landscape
B2B eCommerce operates fundamentally differently from B2C. Buyers need company accounts with role-based permissions, negotiated pricing, purchase order approval workflows, and quick-order capabilities. Magento 2 Commerce (Adobe Commerce) includes a comprehensive B2B module that addresses these requirements out of the box.
This guide covers practical implementation of the core B2B features, including configuration, customization, and performance considerations for Magento 2 stores handling enterprise B2B workloads.
Company Account Structure
B2B buyers operate within organizational hierarchies. The Company Account feature in Magento 2 models these relationships:
Company Admin: Creates and manages the company account, assigns roles, and manages users.
Roles and Permissions: Define what each team member can do — browse catalog, add to cart, place orders, approve purchases, manage company users.
Programmatic Company Creation
use Magento\Company\Api\CompanyRepositoryInterface;
use Magento\Company\Api\Data\CompanyInterfaceFactory;
class CompanyService
{
public function __construct(
private CompanyRepositoryInterface $companyRepository,
private CompanyInterfaceFactory $companyFactory
) {}
public function createCompany(array $data): int
{
$company = $this->companyFactory->create();
$company->setCompanyName($data['name']);
$company->setCompanyEmail($data['email']);
$company->setStreet($data['street']);
$company->setCity($data['city']);
$company->setCountryId($data['country']);
$company->setPostcode($data['postcode']);
$company->setTelephone($data['phone']);
$company->setSuperUserId($data['admin_user_id']);
$company->setStatus(1); // Active
$saved = $this->companyRepository->save($company);
return (int) $saved->getId();
}
}
Role Configuration
use Magento\Company\Api\RoleRepositoryInterface;
use Magento\Company\Api\Data\RoleInterfaceFactory;
class RoleService
{
private const PERMISSIONS = [
'Magento_Company::index' => 'allow',
'Magento_Sales::place_order' => 'allow',
'Magento_Sales::view_orders' => 'allow',
'Magento_NegotiableQuote::manage' => 'allow',
'Magento_PurchaseOrder::approve' => 'deny',
];
public function createBuyerRole(int $companyId): void
{
$role = $this->roleFactory->create();
$role->setCompanyId($companyId);
$role->setRoleName('Buyer');
$role->setPermissions($this->buildPermissionTree(self::PERMISSIONS));
$this->roleRepository->save($role);
}
}
Shared Catalogs
Shared Catalogs allow you to create custom pricing tiers visible only to specific companies. This replaces the need for complex catalog price rules.
Creating a Custom Shared Catalog
In the admin panel: Catalog > Shared Catalogs > Add Shared Catalog
Programmatically:
use Magento\SharedCatalog\Api\SharedCatalogRepositoryInterface;
use Magento\SharedCatalog\Api\Data\SharedCatalogInterfaceFactory;
$catalog = $this->sharedCatalogFactory->create();
$catalog->setName('Gold Tier Partners');
$catalog->setDescription('Preferred pricing for gold tier B2B partners');
$catalog->setType(SharedCatalogInterface::TYPE_CUSTOM);
$catalog->setTaxClassId(2);
$this->sharedCatalogRepository->save($catalog);
Assigning Custom Prices
use Magento\SharedCatalog\Api\ProductManagementInterface;
// Assign products to shared catalog
$this->productManagement->assignProducts(
$sharedCatalogId,
$productSkus
);
// Set custom tier prices
$tierPrice = $this->tierPriceFactory->create();
$tierPrice->setCustomerGroupId($sharedCatalog->getCustomerGroupId());
$tierPrice->setQty(1);
$tierPrice->setValue(89.99); // Custom price for this catalog
$tierPrice->setWebsiteId(0);
$this->tierPriceStorage->update([$tierPrice]);
Negotiable Quotes
The negotiable quote workflow enables buyers to request custom pricing on orders, with back-and-forth negotiation between buyer and sales representative.
Quote Workflow
- Buyer adds items to cart and requests a quote
- Sales rep receives notification and reviews the request
- Sales rep adjusts pricing (line item or total discount)
- Buyer reviews, accepts, or counters
- Accepted quote converts to an order
Custom Quote Validation
use Magento\NegotiableQuote\Api\NegotiableQuoteManagementInterface;
class QuoteApprovalService
{
public function validateAndApprove(int $quoteId, float $maxDiscount): bool
{
$quote = $this->quoteRepository->get($quoteId);
$negotiableQuote = $quote->getExtensionAttributes()
->getNegotiableQuote();
$originalTotal = $quote->getBaseGrandTotal();
$negotiatedTotal = $negotiableQuote->getNegotiatedPriceValue();
$discountPercent = (($originalTotal - $negotiatedTotal) / $originalTotal) * 100;
if ($discountPercent > $maxDiscount) {
$negotiableQuote->setStatus(
NegotiableQuoteInterface::STATUS_DECLINED
);
$this->quoteRepository->save($quote);
return false;
}
$this->negotiableQuoteManagement->adminSend($quoteId);
return true;
}
}
Purchase Order Approval Workflows
Enterprise buyers often require multi-level approval before a purchase order is placed. Magento 2 B2B supports configurable approval rules:
Approval Rule Configuration
// Create approval rule: orders over $5,000 need manager approval
$rule = $this->approvalRuleFactory->create();
$rule->setName('Large Order Approval');
$rule->setDescription('Orders exceeding $5,000 require manager approval');
$rule->setIsActive(true);
$rule->setCompanyId($companyId);
$rule->setConditionsSerialized(json_encode([
'type' => 'Magento\PurchaseOrderRule\Model\Rule\Condition\Combine',
'conditions' => [
[
'type' => 'Magento\PurchaseOrderRule\Model\Rule\Condition\Address',
'attribute' => 'grand_total',
'operator' => '>',
'value' => 5000,
],
],
]));
$rule->setApproverRoleIds([$managerRoleId]);
$this->approvalRuleRepository->save($rule);
Quick Order and Requisition Lists
B2B buyers frequently reorder the same products. Requisition Lists function as persistent shopping lists:
use Magento\RequisitionList\Api\RequisitionListRepositoryInterface;
$list = $this->requisitionListFactory->create();
$list->setName('Monthly Office Supplies');
$list->setCustomerId($customerId);
$list->setDescription('Standard monthly order for building A');
$this->requisitionListRepository->save($list);
// Add items to requisition list
foreach ($skus as $sku => $qty) {
$item = $this->requisitionListItemFactory->create();
$item->setSku($sku);
$item->setQty($qty);
$item->setListId($list->getId());
$this->requisitionListItemRepository->save($item);
}
Performance Considerations for B2B
B2B catalogs often contain hundreds of thousands of SKUs with complex pricing rules. Performance optimization is critical:
- Shared Catalog Indexing: Shared catalog price indexing can be resource-intensive. Run indexers in
schedulemode with cron and allocate dedicated worker processes. - Company Structure Caching: Cache the company hierarchy and permission tree in Redis to avoid database queries on every page load.
- Quote Calculation: Negotiable quotes with many line items require optimized price calculation. Pre-calculate and cache tier prices.
- Elasticsearch Tuning: B2B search queries often include SKU-based searches and attribute filtering. Configure Elasticsearch with custom analyzers for SKU patterns.
Integration Patterns
B2B implementations typically integrate with ERP systems. Use Magento's async REST API for bulk operations:
curl -X POST "https://store.example.com/rest/async/bulk/V1/products" \
-H "Authorization: Bearer admin_token" \
-H "Content-Type: application/json" \
-d '[
{"product": {"sku": "PART-001", "name": "Widget A", "price": 12.99}},
{"product": {"sku": "PART-002", "name": "Widget B", "price": 15.99}}
]'
The async API queues operations in RabbitMQ, processes them in the background, and provides a bulk operation status endpoint for monitoring progress.
Best Practices
- Start with company account structure and roles before implementing complex features
- Use shared catalogs for pricing tiers instead of complex catalog price rules
- Test approval workflows with real business scenarios from your sales team
- Implement ERP sync as an asynchronous, event-driven process
- Monitor server performance closely during B2B catalog reindexing
B2B commerce on Magento 2 requires careful planning around organizational structures, pricing models, and approval workflows. The platform provides the building blocks, but success depends on mapping business requirements accurately to technical implementation.
Need help with this?
Our team handles this kind of work daily. Let us take care of your infrastructure.
Related Articles
How to Boost Magento 2 Performance in a Few Easy Steps
Magento 2 delivers incredible flexibility for eCommerce, but without proper optimization it can become sluggish. This guide walks through ten proven DevOps strategies to dramatically speed up your store, from PHP upgrades and full-page caching to Varnish, Redis, CDN configuration, and ongoing code audits.
MagentoHow to Upgrade Magento 2 from 2.4.7 to 2.4.8
Keeping Magento current is critical for security, performance, and compatibility. This step-by-step guide walks developers through upgrading from Magento 2.4.7 to 2.4.8, covering system requirements, pre-upgrade checks, Git workflow, Composer commands, and post-upgrade validation.
MagentoHow to Completely Disable "Compare Products" in Magento 2
Magento's built-in Compare Products feature can add unnecessary clutter and slow down page loads. This guide shows you how to fully remove it using layout XML overrides, CSS rules, and a quick CLI deploy -- keeping your storefront clean and fast.