Recursos B2B do Adobe Commerce: visão geral para desenvolvedores
O Adobe Commerce traz um conjunto de módulos B2B que cobrem o que compradores de atacado esperam: contas de empresa com vários usuários, catálogos e preços específicos por cliente, cotações que vão e voltam com um representante de vendas, purchase orders que precisam de aprovação e reposição rápida por SKU. Nada disso existe no Magento Open Source. Vem como um pacote Composer separado que só instala no Adobe Commerce, e mexe em checkout, preços, contas de cliente e no admin de formas que o desenvolvedor precisa entender antes de construir qualquer coisa em cima.
Este artigo é uma visão geral para desenvolvedores. Mostra o que cada recurso faz, quais módulos o implementam, como habilitar, onde ele aumenta a carga e o que observar ao escrever código custom em uma loja B2B.
Instalando a extensão B2B
Os recursos B2B ficam no metapackage magento/extension-b2b. Ele só está disponível no repo.magento.com para licenças do Adobe Commerce, e a versão precisa bater com a release do Adobe Commerce que você roda. Confira a tabela de compatibilidade nas release notes antes de dar o require.
composer require magento/extension-b2b
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush
Depois de instalar, os recursos são ligados por website em Stores > Configuration > General > B2B Features. As contas de empresa precisam ser habilitadas primeiro, porque a maioria dos outros recursos depende de o comprador pertencer a uma empresa. Shared catalogs, negotiable quotes, quick order, requisition lists e purchase orders têm cada um o seu próprio switch.
Contas de empresa
O módulo Magento_Company adiciona uma entidade empresa acima do cliente. Uma empresa tem um usuário admin (o comprador que a registrou), usuários adicionais, times, um endereço legal, um representante de vendas escolhido entre os usuários do admin e um customer group que define os preços. Os admins da empresa gerenciam seus próprios usuários e uma árvore de roles na storefront. Cada role libera ou nega recursos como ver pedidos, fazer pedidos, usar cotações ou gerenciar usuários.
Em código custom, a necessidade mais comum é descobrir a qual empresa o cliente atual pertence. A relação é exposta como um extension attribute do cliente, e o módulo tem um service para carregar a própria empresa.
<?php
declare(strict_types=1);
namespace Vendor\B2bTools\Model;
use Magento\Company\Api\CompanyManagementInterface;
use Magento\Company\Api\Data\CompanyInterface;
use Magento\Customer\Api\CustomerRepositoryInterface;
class CompanyResolver
{
public function __construct(
private readonly CustomerRepositoryInterface $customerRepository,
private readonly CompanyManagementInterface $companyManagement
) {
}
public function getCompanyId(int $customerId): ?int
{
$customer = $this->customerRepository->getById($customerId);
$attributes = $customer->getExtensionAttributes()?->getCompanyAttributes();
$companyId = $attributes?->getCompanyId();
return $companyId ? (int) $companyId : null;
}
public function getCompany(int $customerId): ?CompanyInterface
{
return $this->companyManagement->getByCustomerId($customerId);
}
}
Lembre que um usuário da empresa pode estar inativo enquanto o registro do cliente continua existindo. Se a sua lógica libera algo com base na participação em uma empresa, verifique também o status da empresa. Empresas bloqueadas ou rejeitadas não devem receber preços B2B nem opções de pagamento.
Shared catalogs
O Magento_SharedCatalog controla quais produtos e categorias uma empresa enxerga e quanto ela paga. Existe um shared catalog público para visitantes e clientes de varejo, e quantos custom você quiser atribuídos a empresas. Por baixo, cada shared catalog está ligado a um customer group. A visibilidade dos produtos é aplicada pelas category permissions, que é outro recurso do Adobe Commerce, e os preços customizados são gravados como tier prices daquele customer group.
Esse desenho tem duas consequências que você vai sentir no desenvolvimento:
- Salvar um shared catalog com muitos produtos grava muitas linhas de tier price e de permissão. O trabalho é empurrado para consumers da message queue, como
sharedCatalogUpdatePriceesharedCatalogUpdateCategoryPermissions. Se os consumers não estão rodando, as alterações no admin parecem não ter feito nada. Rodebin/magento queue:consumers:listpara ver a lista completa na sua versão e garanta que o cron ou um supervisor os execute. - Qualquer código custom que consulte produtos diretamente, como um feed, uma listagem custom ou um resolver de GraphQL, pode ignorar as category permissions e vazar produtos que a empresa não deveria ver. Passe pelas camadas padrão de collection e repository, e teste logado como usuário de uma empresa.
Os shared catalogs também mudam como o full page cache varia. As páginas são cacheadas por customer group, então uma loja com centenas de empresas em shared catalogs separados acaba com muitas variações de cache da mesma página de categoria. Se performance importa, agrupe as empresas em poucos catálogos em vez de um catálogo por empresa.
Negotiable quotes
O Magento_NegotiableQuote permite que o comprador transforme um carrinho em um pedido de cotação. O vendedor edita preços e quantidades no admin, adiciona comentários e devolve. Quando os dois lados concordam, o comprador faz o checkout com os preços negociados travados. A cotação é um registro de quote comum com uma tabela extra de negotiable quote ligada a ele, mais um histórico de cada alteração.
Como o preço negociado precisa sobreviver ao checkout, o módulo afeta a coleta de totais. Totals collectors custom e plugins no cálculo de preço precisam ser testados especificamente contra negotiable quotes. Uma taxa ou desconto que funciona em um carrinho normal pode ser aplicado duas vezes ou ignorado quando a cotação é convertida, dependendo de onde você se encaixa.
Purchase orders e regras de aprovação
Com purchase orders habilitados, fazer um pedido em uma conta de empresa cria primeiro um purchase order. As regras de aprovação definidas pelo admin da empresa decidem se ele precisa de aprovação, por exemplo quando o total do pedido passa de um limite ou um método de envio específico é usado. Só depois da aprovação ele vira um sales order. Os módulos envolvidos são Magento_PurchaseOrder e Magento_PurchaseOrderRule.
Para integrações isso importa muito. Um conector de ERP que escuta pedidos não vai ver nada até a aprovação acontecer, e alguns métodos de pagamento se comportam diferente porque o pagamento é capturado na conversão, não quando o comprador clica no botão. O pagamento em conta (payment on account), fornecido pelo Magento_CompanyCredit, encaixa bem nesse fluxo porque cobra de um limite de crédito em vez de um cartão.
Quick order e requisition lists
O Magento_QuickOrder dá aos compradores uma página onde eles digitam ou colam SKUs e quantidades, ou enviam um CSV, e adicionam tudo ao carrinho de uma vez. O Magento_RequisitionList permite salvar listas nomeadas de produtos para compras recorrentes. Os dois são simples na superfície, mas dependem de busca por SKU. Se o seu catálogo usa produtos configuráveis, o comprador precisa informar o SKU do filho. Se você tem tipos de produto ou opções de produto custom, teste se eles podem ser adicionados por esses fluxos, já que eles pulam a página normal do produto.
GraphQL e B2B headless
As releases recentes da 2.4 expõem a maior parte dos recursos B2B pelo GraphQL: dados e usuários da empresa, requisition lists, negotiable quotes e purchase orders. Se você monta uma storefront headless, confira a referência de GraphQL da sua versão exata, porque a cobertura cresceu release a release. Os arquivos de schema ficam nos módulos B2B que terminam em GraphQl, e você pode estendê-los do mesmo jeito que os schemas do core. A abordagem geral é a mesma de um resolver de query GraphQL custom.
O que observar ao construir em uma loja B2B
- O customer group é sobrecarregado. Os shared catalogs são donos do customer group de cada empresa. Não reaproveite customer groups para lógicas não relacionadas, como tax classes ou segmentos de marketing, sem checar como isso interage com a atribuição de catálogo.
- Os consumers precisam rodar. Atualizações de shared catalog, de preço de cotação e o processamento de purchase orders dependem de consumers de fila. Trate a saúde dos consumers como parte do monitoramento. Veja consumers do RabbitMQ no Magento 2 para a configuração.
- As permissões são aplicadas em vários lugares. As roles da empresa são checadas nos controllers e na UI da storefront. Uma página custom que lista pedidos ou invoices também deve checar as permissões da empresa, não só se o cliente está logado.
- A indexação cresce com os catálogos. Mais customer groups significa mais linhas nos índices de preço e de permissão. Indexers em modo update by schedule com um cron funcionando são obrigatórios. Os detalhes estão em modos de indexer explicados.
- Extensões de terceiros. Muitas extensões de marketplace nunca foram testadas com B2B. Teste extensões de checkout, preço e conta de cliente com usuários de empresa antes de se comprometer com elas.
Quando a suíte B2B faz sentido
Os módulos B2B servem para lojas em que os compradores são empresas com várias pessoas fazendo pedidos, onde os preços são negociados por conta e onde fluxos de aprovação fazem parte do jeito de comprar dos clientes. Se o requisito é só um preço de atacado para um grupo de clientes, tier prices e customer groups do Open Source podem bastar, e isso evita muitas peças móveis. Se você ainda está decidindo a edição, a comparação mais ampla está em Magento Open Source vs Adobe Commerce.
FAQ
Posso instalar a extensão B2B no Magento Open Source?
Não. O pacote magento/extension-b2b só está disponível para licenças do Adobe Commerce e depende de módulos do Commerce, como category permissions. Lojas Open Source precisam de extensões B2B de terceiros ou desenvolvimento custom.
Por que as alterações no shared catalog não aparecem na storefront?
As atualizações de preço e permissão do shared catalog são processadas por consumers da message queue. Se os consumers ou o cron não estão rodando, as alterações ficam na fila. Verifique os consumers, depois os indexers e o cache.
Como pego a empresa de um cliente logado no código?
Leia o extension attribute company_attributes do cliente e chame getCompanyId(), ou use CompanyManagementInterface::getByCustomerId() para carregar a entidade da empresa.
Purchase orders afetam integrações com ERP?
Sim. Com purchase orders habilitados, o sales order só existe depois da aprovação. Integrações que escutam novos pedidos só vão ver o pedido nesse momento, então planeje o fluxo considerando esse atraso.
Atendo como freelancer em Magento e Adobe Commerce, incluindo projetos e integrações B2B. Se precisar de ajuda com isso, fale comigo.
Artigos relacionados
Shipping method customizado no Magento 2: crie um módulo de carrier
Como criar um shipping method customizado no Magento 2.4: config.xml, system.xml, um carrier model com collectRates, regras de frete grátis e APIs externas de tarifa.
Checklist de limpeza de malware no Magento 2 para lojistas
Checklist defensivo para uma loja Magento 2 hackeada: sinais de comprometimento, achar código injetado em arquivos e banco, rebuild limpo, novas credenciais e hardening.
Backup e restore no Magento 2: o que salvar e como
Como fazer backup e restore de uma loja Magento 2: dumps de banco que importam sem erro, mídia, env.php e a chave de criptografia, cópias offsite e restores testados.
Exportar pedidos do Magento 2 para o ERP sem perder nenhum
Um jeito confiável de exportar pedidos do Magento 2 para um ERP: colunas de status, o evento certo, message queue, retries, idempotência e um cron de segurança.