Skip to main content
Back to Articles
MagentoFebruary 5, 20269 min read

Magento 2 B2B Features: Implementation Guide

Implement Magento 2 B2B commerce features including company accounts, shared catalogs, negotiated quotes, and purchase order workflows for enterprise.

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

  1. Buyer adds items to cart and requests a quote
  2. Sales rep receives notification and reviews the request
  3. Sales rep adjusts pricing (line item or total discount)
  4. Buyer reviews, accepts, or counters
  5. 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 schedule mode 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.