Preço de uma loja gravado como preço de todas
No marketplace, o administrador alterava o preço de uma loja e o valor ia para o preço de cadastro do produto, afetando todas as lojas sem preço próprio. Rastreei a regressão até uma mudança de nove meses antes e corrigi a gravação, com 15 cenários de teste.
- Papel
- Desenvolvedor responsável, do diagnóstico à entrega
- Contexto
- Plataforma de e-commerce com marketplace
- Stack
- PHP, Symfony, Twig, JavaScript, MySQL, PHPUnit
- Time
- Solo
- Período
- 2026
Case anonimizado: nomes de empresa, cliente e pessoas foram omitidos ou trocados.
01. Situação
O admin mudava o preço de uma loja e a loja continuava com o preço antigo
Em um marketplace da plataforma, o administrador geral abria a lista de preço padrão, filtrava por uma loja e alterava o preço de um produto. Ao reabrir a tela, a coluna da loja voltava ao valor anterior, e a vitrine, o carrinho e o checkout continuavam com o preço antigo. Quando o próprio lojista fazia a mesma alteração pelo login dele, funcionava.
Reproduzi o problema e fui atrás de onde o valor ia parar. Ele não se perdia: era gravado no preço de cadastro do produto. Foi aí que entendi a gravidade real, porque o preço de cadastro é o último nível da cascata de preço da vitrine.
- Lista do cliente ou do perfil
- Lista padrão da loja
- Lista global
- Preço de cadastro do produto
A loja escolhida não via a mudança, porque tinha preço próprio. Todas as outras lojas sem preço próprio, e o próprio marketplace, passavam a cobrar o valor novo. O chamado falava de um preço que não salvava; o que eu encontrei foi um preço sendo alterado em silêncio para quem não tinha pedido.
02. Investigação
A tela mostrava a lista da loja e enviava a lista do produto
Analisei o template, o JavaScript da tela, o controller e a cascata de preço. No admin, "preço padrão" é uma lista virtual, com id 0, que significa "preço de cadastro". A lista padrão de cada loja é outra lista, real, e não é filha da virtual.
O template detectava o admin com loja escolhida e exibia a lista da loja, mas o campo continuava enviando id 0. No backend, id 0 sem loja na sessão do admin levava direto ao preço de cadastro, antes de considerar a loja que vinha no request.
Faltava saber por que isso tinha começado. Percorri o histórico do git e cheguei à origem: uma mudança feita cerca de nove meses antes, para corrigir as listas por centro de distribuição, trocou o id enviado pela tela. O esquema novo funciona para as listas nomeadas, que têm lista pai, mas o "preço padrão" não tem, e ficou de fora.
Era a correção mais óbvia. Analisei o efeito: voltar a enviar o id real da lista da loja faria o backend procurar uma lista filha inexistente e criar uma lista duplicada para a loja. Descartada.
03. Solução
Redirecionar a gravação para a lista da loja, pelo caminho que o lojista já usava
Em vez de criar um fluxo novo, levei a gravação do admin para o caminho que o lojista já usava e que funcionava em produção. Adicionei um método privado chamado só na gravação: quando o admin envia "preço padrão" com uma loja válida que tem lista padrão, a gravação passa a usar a lista dessa loja. Se a loja não tiver lista padrão, a resposta é um erro claro e nada é gravado.
Escolha
Resolver a loja só na gravação
A função que lê a lista também atende a tela e a exportação. Mudá-la alteraria o que o admin vê e o relatório, então restringi a mudança ao ponto do defeito.
Escolha
Antes da checagem de permissão
Posicionei a resolução antes da permissão, para que ela seja verificada sobre a lista que de fato será gravada.
Trade-off
Loja sem lista padrão recebe erro
Manter a gravação no preço de cadastro seria manter o defeito, e criar a lista na hora mexeria no cadastro de loja. Preferi recusar com uma mensagem clara.
Cuidado
Dados já afetados
Preços de cadastro alterados pelo defeito não voltam com o deploy. Avisei isso no chamado e entreguei uma consulta para o time localizar os casos.
Antes de corrigir, troquei as expectativas dos testes para o comportamento certo e vi os quatro cenários do defeito falharem. Depois da correção, os 15 cenários passaram. Para garantir que eu não tinha quebrado nada, rodei a suíte completa com e sem a mudança e comparei: as falhas que já existiam eram exatamente as mesmas nas duas execuções.
04. Resultado
A alteração fica na loja escolhida
- cenários de teste, admin e lojista
- 15
- cenários do defeito falhando
- 4 → 0
- desde a mudança que causou a regressão
- ~9 meses
A edição do administrador vai para o preço da loja escolhida e aparece na vitrine dela. As outras lojas e o marketplace deixaram de ter o preço alterado sem querer. Admin sem loja escolhida, listas nomeadas e o lojista continuam como antes.
A correção fecha uma regressão que estava em produção havia meses. Junto com ela, entreguei a consulta para identificar lojas sem lista padrão e a orientação sobre os preços que precisavam de ajuste manual.