dfomnibus: conformidade com a diretiva Omnibus no PrestaShop
Instalação, configuração, cron, modos de cálculo, painel e resolução de problemas do módulo dfomnibus, para a conformidade com a diretiva europeia Omnibus.
O módulo dfomnibus coloca a sua loja PrestaShop em conformidade com a diretiva europeia 2019/2161, conhecida por Omnibus, em vigor em toda a União Europeia desde 28 de maio de 2022. Constrói automaticamente o histórico de preços de cada produto e mostra, sempre que houver uma promoção ativa, o preço mais baixo praticado nos 30 dias anteriores.
Em Portugal, a diretiva Omnibus foi transposta pelo Decreto-Lei n.º 66/2021, que alterou o regime dos preços e das reduções: qualquer anúncio de redução de preço tem de indicar o preço mais baixo praticado nos 30 dias anteriores. A fiscalização cabe à ASAE. É exatamente esta obrigação que o módulo automatiza.
Compatibilidade: PrestaShop 8.0 a 9.x. PHP 7.4 a 8.3. Multiloja, multimoeda e multicombinação suportados nativamente. Sem componentes de terceiros, sem CDN e compatível com o RGPD.
Instalação
A instalação demora menos de cinco minutos.
- Descarregue o ficheiro
dfomnibus_v1.0.1.zipa partir da sua área de cliente DataFirefly. - No back-office do PrestaShop, vá a Módulos → Gestor de módulos → Carregar um módulo.
- Envie o ZIP. O PrestaShop cria as tabelas, gera um token de cron e regista os hooks necessários.
- Clique em Configurar para abrir o ecrã de definições.
Duas tabelas criadas: ps_dfomnibus_price_history, para os instantâneos, e ps_dfomnibus_compliance_log, para os eventos de conformidade (reservada para evoluções futuras). O prefixo ps_ é automaticamente substituído pelo seu.
Agendamento do cron diário
O cron inicia o histórico do seu catálogo e garante a continuidade dos instantâneos diários, mesmo nos produtos cujo preço nunca muda. Sem cron ativo, o módulo funciona, mas o histórico fica limitado aos produtos alterados manualmente.
Obter o token
Abra a página de configuração do módulo. O token de cron apresentado é único para a sua instalação. Obtém um URL com esta forma:
https://a-sua-loja.pt/modules/dfomnibus/cron.php?token=O_SEU_TOKEN
Agendamento por cron Unix
Acrescente a linha seguinte ao seu crontab e ajuste a hora conforme o seu tráfego (idealmente, em horas de menor movimento):
15 3 * * * curl -s "https://a-sua-loja.pt/modules/dfomnibus/cron.php?token=O_SEU_TOKEN" > /dev/null
Agendamento por CLI
Se preferir evitar qualquer exposição por HTTP, execute o cron diretamente na linha de comandos:
php /caminho/para/a-sua-loja/modules/dfomnibus/cron.php token=O_SEU_TOKEN
Segurança do token: o módulo usa hash_equals() para comparar os tokens, o que protege contra ataques por medição de tempo. Nunca partilhe este token e gere um novo se suspeitar de compromisso (botão Gerar novo token na configuração).
Confirme que o fuso horário do servidor está em Europe/Lisbon. A janela dos 30 dias é calculada a partir das datas dos instantâneos: com o servidor em UTC, no horário de verão os instantâneos das primeiras horas do dia ficam registados na véspera, o que desloca a fronteira da janela num controlo ao dia.
Configuração das opções
Ativação da apresentação
O interruptor Ativar a apresentação controla a inserção da mensagem de conformidade por baixo do preço do produto. Pode desativá-lo temporariamente para manter a recolha do histórico sem mostrar a menção no front-office, o que é útil durante uma migração ou nos testes.
Modo de cálculo
Há dois modos disponíveis:
- Estrito: o preço de referência é o mínimo verificado nos 30 dias que antecedem o início efetivo da promoção em curso. Corresponde à letra da diretiva.
- Conservador (recomendado por predefinição): o preço de referência é o mínimo dos últimos 30 dias corridos. É uma interpretação menos favorável ao comerciante, mas mais defensável numa inspeção.
Que modo escolher? Se a sua loja tem uma política promocional clara, com datas de início e de fim bem registadas, o modo estrito serve. Em caso de dúvida, ou se as suas regras de SpecificPrice mudam com frequência sem uma fronteira nítida entre períodos com e sem promoção, o modo conservador é mais seguro.
Período de referência
O período está fixado em 30 dias por predefinição, em conformidade com a diretiva. Pode aumentá-lo (60 ou 90 dias) para ser ainda mais prudente, mas o valor mínimo continua a ser 30 dias.
Exclusão dos produtos recentes
A opção Excluir os produtos com menos de X dias oculta a apresentação nos produtos demasiado recentes. O valor predefinido são 30 dias, o que é coerente com o espírito da diretiva, que só se aplica a produtos com um histórico de preços significativo.
Restrição à UE
Se vende dentro e fora da UE, assinale Restringir a apresentação à União Europeia. O módulo deteta o país do cliente por esta ordem:
- Morada de entrega do cliente com sessão iniciada
- Morada do carrinho em curso
- País predefinido da loja
Se nenhuma destas informações estiver disponível, a apresentação fica ativa por predefinição, para evitar qualquer risco de incumprimento involuntário.
Os Açores e a Madeira são território nacional e da UE: uma entrega nas ilhas está abrangida pela obrigação exatamente como uma entrega no continente. A restrição à UE destina-se a mercados fora da União, não às regiões autónomas.
Ocultar quando o preço é igual
A opção Ocultar se o preço for idêntico retira a mensagem quando o preço atual corresponde exatamente ao preço mais baixo dos últimos 30 dias. É útil para não mostrar uma informação sem valor acrescentado para o consumidor.
Desconto real
Ative Mostrar o desconto real para completar a mensagem com a percentagem calculada sobre o preço Omnibus, e não sobre o preço riscado. Por exemplo, um produto a 89 €, em promoção a 59 €, com um preço Omnibus de 65 €, mostra -9,2 % de desconto real, em vez dos -33 % calculados sobre o preço riscado. É mais honesto, mas cada comerciante decide.
Anunciar uma percentagem calculada sobre um preço riscado que já não corresponde à realidade aproxima-se do que o Decreto-Lei n.º 57/2008 trata como prática enganosa. Se a diferença entre as duas percentagens for grande, é sinal de que o preço riscado ficou desatualizado: mostrar o desconto real é a opção mais defensável.
Gráfico
O gráfico de 30 dias pode aparecer num separador dedicado da ficha de produto ou em linha, por baixo do preço. É carregado de forma diferida por IntersectionObserver e só é acionado quando entra no viewport, o que garante impacto nulo nos Core Web Vitals das suas fichas de produto.
Seguimento por combinação
Assinale Seguir as combinações se os seus produtos tiverem preços diferentes por combinação (por exemplo, tamanhos XL com suplemento). O histórico passa então a ser segmentado por id_product_attribute e a menção Omnibus adapta-se ao preço da combinação selecionada.
Retenção
A duração de conservação predefinida é de 365 dias. Depois disso, o histórico é limpo automaticamente na execução do cron. O valor mínimo é de 60 dias, para garantir margem de segurança face à janela legal de 30 dias.
Uma retenção de 365 dias é uma boa escolha: dá-lhe folga para responder a uma reclamação ou a um pedido da ASAE meses depois da campanha, sem guardar dados pessoais, já que o histórico só contém preços.
Painel de conformidade
Acessível em Módulos → Painel DataFirefly Omnibus, o painel reúne:
- O número de produtos acompanhados
- O total de instantâneos registados
- A data e a hora da última passagem do cron
- A lista de produtos com, em cada um, a data da primeira captura, a data da última captura, o preço mais baixo dos últimos 30 dias e um indicador de promoção ativa
Em cada produto, há três ações disponíveis:
- Ver o histórico: mostra até 1000 instantâneos com data e hora
- Instantâneo manual: força uma captura imediata
- Eliminar o histórico: repõe o seguimento deste produto (a usar com prudência)
Exportação CSV
Na vista de histórico de um produto, o botão Exportar em CSV gera um ficheiro com todas as colunas com data e hora (data, preço sem IVA, preço com IVA, moeda, loja, combinação, indicador de promoção e origem da captura). O formato está pronto a arquivar ou a entregar num controlo da ASAE.
Comportamento no front-office
Na ficha de produto, assim que houver uma promoção ativa, aparece automaticamente esta menção por baixo do preço:
Preço mais baixo dos últimos 30 dias: 65,00 €
A mensagem é traduzida segundo o idioma da loja (francês, inglês, espanhol e alemão). A apresentação usa o hook padrão displayProductPriceBlock e funciona com todos os temas que respeitem os padrões do PrestaShop (Classic, Hummingbird, Warehouse, Transformer e Panda).
O português não está entre os quatro idiomas fornecidos: traduza a menção em Internacional > Traduções antes de a ativar. Aqui, isso não é uma questão de conforto, mas de conformidade: é esta frase que cumpre a obrigação do Decreto-Lei n.º 66/2021 perante o consumidor português, e uma informação obrigatória apresentada noutra língua dificilmente será considerada prestada de forma clara e compreensível.
Apresentação única por página: o módulo inclui uma proteção static $rendered, que garante que a menção aparece apenas uma vez por página, mesmo que o hook displayProductPriceBlock seja chamado várias vezes (blocos de resumo, barra fixa e outros).
Multiloja e multimoeda
O histórico é guardado por combinação única de (id_product, id_product_attribute, id_shop, id_currency). Cada loja da sua instalação conserva, por isso, o seu próprio histórico, e cada moeda ativa tem a sua curva de preços. Não há conversão instantânea: os montantes apresentados correspondem exatamente ao que foi registado no momento da captura.
Resolução de problemas
A menção não aparece na ficha de produto
Verifique por esta ordem:
- A opção Ativar a apresentação está assinalada na configuração?
- O cron já correu pelo menos uma vez? Se não, não existe qualquer histórico.
- A restrição à UE está ativa e está a testar a partir de um país fora da UE?
- A opção Ocultar se o preço for idêntico está ativa e o preço atual corresponde ao mínimo?
- O produto tem menos de 30 dias, com a opção de exclusão de novidades ativa?
O gráfico não carrega
Abra a consola do navegador. O módulo espera um ponto de entrada AJAX exposto pelo controlador de front-office pricehistory. Confirme que nenhum sistema de cache ou firewall interceta esta rota. Se usar um CDN, autorize explicitamente os URL /module/dfomnibus/pricehistory.
O cron devolve um erro 403 ou 401
O token do URL não corresponde ao registado. Volte à configuração do módulo e copie o token atual. Se suspeitar de uma fuga, clique em Gerar novo token e atualize o seu cron Unix.
Erro de SQL no momento do instantâneo
Se estiver na versão 1.0.0, atualize para a 1.0.1. A versão inicial tinha um defeito em três consultas Db::getRow(), que acrescentavam um LIMIT 1 manual quando o PrestaShop já acrescenta um automaticamente, produzindo um LIMIT 1 LIMIT 1 inválido em SQL. Ver o registo de alterações.
Perguntas frequentes
O módulo é obrigatório para a minha loja?
Sim, se vende a consumidores estabelecidos na União Europeia e mostra preços reduzidos, promoções, códigos de desconto, saldos ou qualquer menção de redução. A obrigação aplica-se sem limiar de volume de negócios.
Qual é a diferença face às CartRule?
O módulo acompanha apenas os preços vindos dos SpecificPrice do PrestaShop (descontos de produto, descontos por quantidade, descontos por grupo de clientes). As regras de carrinho (CartRule) aplicam-se no checkout e não alteram o preço unitário apresentado na ficha de produto, pelo que ficam fora do âmbito da diretiva.
Como funciona exatamente o modo estrito?
O módulo procura no histórico o último instantâneo sem promoção e depois o primeiro instantâneo com promoção que se lhe segue. Essa data é o início da promoção em curso. A janela de referência passa a ser os 30 dias anteriores a essa data. Se não for possível detetar uma passagem de sem promoção para com promoção, o módulo muda automaticamente para o modo conservador.
Posso ocultar a mensagem em certos produtos?
O módulo aplica-se globalmente, mas a opção de exclusão dos produtos recentes e a opção de ocultar quando o preço é igual cobrem a maioria dos casos em que a apresentação não traz informação útil.
É compatível com preços com e sem IVA?
Sim. O módulo regista os dois montantes (price_tax_excl e price_tax_incl) em cada instantâneo e mostra o que a loja usa. Se mudar de um modo para o outro, o histórico continua aproveitável.
Numa loja portuguesa que vende a consumidores, o preço a apresentar é o preço com IVA: é esse que deve figurar na menção. Confirme a definição de apresentação dos preços da sua loja antes de publicar a campanha, para que o preço mais baixo indicado esteja na mesma base do preço que o cliente vê.
Registo de alterações
1.0.1, 14 de maio de 2026
- Correção: remoção do
LIMIT 1manual em três consultasDb::getRow(), que produziam umLIMIT 1 LIMIT 1inválido em SQL. Afetava a proteção de idempotência do registo e a deteção do início da promoção no modo estrito.
1.0.0, 14 de maio de 2026
- Lançamento inicial
- Captura automática do histórico de preços por hooks e cron diário
- Apresentação do preço mais baixo dos 30 dias na ficha de produto
- Gráfico de 30 dias em canvas nativo, com carregamento diferido e cerca de 3 KB
- Painel de conformidade com estatísticas e exportação CSV
- Modos de cálculo estrito e conservador
- Suporte de multiloja, multimoeda e multicombinação
- Restrição à UE configurável, exclusão dos produtos recentes e opção de ocultar quando o preço é idêntico
- Traduções em FR, EN, ES e DE