Frete & Logística

Frete grátis por estado no Magento 2 com regra de carrinho

O marketing pede frete grátis só para São Paulo e Rio. O orçamento de módulo que chega é de quatro dígitos. O Magento já faz isso desde a instalação, com uma pegadinha no meio do caminho.

Por Roger Takemiya · Publicado em · 5 min de leitura

Pedido comum de loja que vende pesado: liberar frete grátis acima de um valor, mas só para quem está perto do centro de distribuição. Quase toda agência responde com orçamento de extensão. Não precisa.

A classe Magento\SalesRule\Model\Rule\Condition\Address já expõe estado, CEP e país como condição de regra de carrinho desde o 2.0. E os 27 estados brasileiros vêm cadastrados de fábrica, pelo data patch InitializeDirectoryData do módulo Directory.

As condições de endereço que já vêm no Magento

Quando você adiciona uma condição em uma regra de carrinho, essa lista sai direto do core:

Rótulo no adminCampo no endereçoTipo
Subtotalbase_subtotalnumérico
Total Items Quantitytotal_qtynumérico
Total Weightweightnumérico
Payment Methodpayment_methodselect
Shipping Methodshipping_methodselect
Shipping Postcodepostcodetexto
Shipping Regionregiontexto
Shipping State/Provinceregion_idselect
Shipping Countrycountry_idselect

A coluna "tipo" não é enfeite: ela decide quais operadores aparecem. Campo select só ganha is, is not e is undefined. Campo texto ganha a lista inteira, incluindo contains e is one of.

É por isso que você abre o Shipping State/Province procurando "is one of" e não acha. Ele é select. Guarde isso, é o que resolve o próximo passo.

Montando a regra para SP e RJ

Em Marketing > Promotions > Cart Price Rules > Add New Rule, na aba Rule Information: marque os websites, marque todos os grupos de cliente e deixe Coupon em No Coupon, para a regra valer sozinha.

Na aba Conditions, monte assim — repare no bloco aninhado:

If ALL of these conditions are TRUE:
    If ANY of these conditions are TRUE:
        Shipping State/Province is São Paulo
        Shipping State/Province is Rio de Janeiro
    Subtotal equals or greater than 199

O bloco de dentro é a opção Conditions Combination, a primeira da lista quando você clica no mais verde. Sem ele, as duas linhas de estado ficariam sob o "ALL" e a regra pediria que o pedido fosse de São Paulo e do Rio ao mesmo tempo — ou seja, nunca pegaria.

Na aba Actions, deixe Apply em Percent of product price discount com Discount Amount em 0 (você não quer desconto no produto, quer no frete) e ponha o campo Free Shipping em For shipment with matching items.

As três opções desse campo, do jeito que estão escritas no core, são:

  • No — o padrão.
  • For matching items only — o frete zera só na parte do carrinho que casa com as condições de item.
  • For shipment with matching items — o frete do pedido inteiro vai a zero. É essa que você quer aqui.

Salve e teste no checkout com um CEP de cada estado, e com um pedido abaixo dos R$ 199 para conferir que a regra realmente não pega. Teste de regra que só valida o caso feliz não vale nada.

O que faz a regra não pegar

O carrier Free Shipping está desligado. Ele vem com carriers/freeshipping/active em 0 de fábrica. A regra marca o pedido como elegível, mas quem monta a linha de R$ 0,00 no checkout é o carrier. Confira com php bin/magento config:show carriers/freeshipping/active.

O estado ainda não existe no carrinho. O region_id só é preenchido depois que o cliente escolhe o estado, no checkout ou no bloco de estimativa de frete. Na página de carrinho vazia de endereço, a condição é falsa e a regra simplesmente não aparece. Isso não é bug, é ordem dos acontecimentos.

Você usou Shipping Region em vez de Shipping State/Province. Esse é o erro que mais me chega. A condição lê o campo region cru do endereço, que é texto livre e pode chegar vazio quando o checkout manda só o region_id. Prefira sempre o Shipping State/Province, que é o campo com identificador de verdade.

Você tentou resolver por CEP com "contains". Cuidado com esse: o contains procura o pedaço em qualquer posição do CEP, não só no começo. Um 013 casa com 01310-100, que é São Paulo, e também com 20130-000, que é Rio. Se for mesmo por CEP, use is one of com a lista separada por vírgula — o core faz o split por vírgula ou ponto e vírgula.

Minha recomendação depois de anos apanhando com isso: faça por estado, não por CEP. Estado é uma lista fechada de 27 valores que o próprio Magento já cadastrou; CEP é texto que o cliente digita, com ou sem hífen, com ou sem espaço.

Perguntas rápidas

Por que Shipping State/Province não tem a opção is one of?

Porque no core esse campo é do tipo select, e select só recebe os operadores is, is not e is undefined. Campos de texto como o CEP é que ganham o is one of.

A regra funciona junto com um cupom de desconto?

Funciona, mas as duas regras são avaliadas separadamente. Se a regra do cupom estiver com Discard subsequent rules em Yes e tiver prioridade mais alta, ela cala a regra de frete. Deixe a de frete com número de prioridade menor.

Dá para excluir alguns produtos do frete grátis?

Dá. Use as condições de item dentro da mesma regra e escolha For matching items only em vez de For shipment with matching items. Aí o frete zera só na parte do carrinho que casa.

Pra conferir na fonte

  1. SalesRule Model/Rule/Condition/Address.php — GitHub
  2. Rule Model/Condition/AbstractCondition.php — GitHub
  3. Directory InitializeDirectoryData.php — GitHub
  4. Free Shipping — Adobe Experience League

frete regra de carrinho estado

Precisa de um orçamento? Ficarei feliz em ajudar. Clique Aqui