# DataFirefly Odoo Connector: guia de instalação e configuração

> Este guia cobre a instalação, a configuração e a exploração da extensão DataFirefly Odoo Connector para Shopware 6.6 e 6.7. No fim, a sua loja sincronizará produtos, stock, clientes e…

- Página: <https://www.datafirefly.com/pt/documentation/df-odoo-connector/>
- Idioma: pt
- Atualizado em: 2026-09-02
- Outros idiomas: [fr](https://www.datafirefly.com/documentation/df-odoo-connector/index.md), [en](https://www.datafirefly.com/en/documentation/df-odoo-connector/index.md), [es](https://www.datafirefly.com/es/documentation/df-odoo-connector/index.md), [de](https://www.datafirefly.com/de/documentation/df-odoo-connector/index.md), [it](https://www.datafirefly.com/it/documentation/df-odoo-connector/index.md), [pl](https://www.datafirefly.com/pl/documentation/df-odoo-connector/index.md), [nl](https://www.datafirefly.com/nl/documentation/df-odoo-connector/index.md)
- Índice: <https://www.datafirefly.com/pt/documentation/llms.txt>

Este guia cobre a instalação, a configuração e a exploração da extensão **DataFirefly Odoo Connector** para Shopware 6.6 e 6.7. No fim, a sua loja sincronizará produtos, stock, clientes e encomendas com a sua instância Odoo através de XML-RPC nativo, sem qualquer dependência externa nem custo adicional de API de terceiros.

## Apresentação

A extensão estabelece uma ponte bidirecional entre o Shopware e o Odoo falando diretamente o protocolo XML-RPC do Odoo (estável desde a versão 8). Sem módulos a instalar do lado do Odoo, sem middleware pago, sem SaaS intermediário.

| Entidade | Odoo → Shopware (pull) | Shopware → Odoo (push) |
| --- | --- | --- |
| Produtos (product.template) | ✅ | ✅ |
| Stock (qty_available / free_qty) | ✅ | — |
| Categorias (product.category) | ✅ | ✅ |
| Clientes (res.partner) | — | ✅ com moradas filhas |
| Encomendas (sale.order) | — | ✅ com confirmação e fatura opcionais |

## Pré-requisitos

- **Shopware** 6.6.x ou 6.7.x (todas as versões menores).
- **PHP** 8.2, 8.3 ou 8.4.
- **Extensões PHP**: curl, xml, simplexml (presentes por predefinição na quase totalidade dos alojamentos).
- **Odoo** 12, 13, 14, 15, 16, 17 ou 18, em Community ou Enterprise. O Odoo.sh, o Odoo Online (SaaS) e as instâncias auto-alojadas funcionam de forma idêntica.
- Um utilizador Odoo dedicado à API (recomendado) com direitos de leitura e escrita nos modelos usados (product.template, product.product, res.partner, sale.order, stock.warehouse, product.category, res.country, account.tax).

## Instalação

### Por carregamento na administração

1. Transfira o arquivo `DfOdooConnector-v1.0.0.zip` a partir da sua conta de cliente.
2. Na administração do Shopware: _Extensões → As minhas extensões → Carregar uma extensão_.
3. Selecione o ZIP e clique em _Instalar_.
4. Ative a extensão clicando no interruptor.

### Por consola SSH

```
cd /caminho/para/shopware
cp DfOdooConnector-v1.0.0.zip custom/plugins/
cd custom/plugins && unzip DfOdooConnector-v1.0.0.zip
sudo -u www-data setsid php bin/console plugin:refresh
sudo -u www-data setsid php bin/console plugin:install --activate DfOdooConnector
sudo -u www-data setsid php bin/console cache:clear
```

Recompilação da administração para carregar o módulo em Vue 3:

```
sudo -u www-data setsid php bin/build-administration.sh
```

**Nota**: a instalação cria duas tabelas: `df_odoo_mapping` (correspondências persistentes Shopware ↔ Odoo) e `df_odoo_log` (registo das operações). Nenhuma tabela existente é alterada.

## Configuração do lado do Odoo

### Criar um utilizador dedicado

É fortemente recomendado criar um utilizador Odoo dedicado à integração em vez de usar uma conta de administrador pessoal. Isso permite auditar com precisão as ações do conector e revogar o seu acesso de forma independente.

1. No Odoo: _Definições → Utilizadores e empresas → Utilizadores_.
2. Crie um utilizador chamado, por exemplo, `Shopware Bridge`.
3. Dê-lhe os direitos necessários: Inventário (utilizador), Vendas (administrador dos documentos), Faturação (utilizador se ativar a criação de fatura), Contactos (utilizador).

### Gerar uma chave de API

1. Inicie sessão no Odoo com esse novo utilizador.
2. Clique no avatar no canto superior direito → _Preferências_.
3. Separador _Conta_ → _Chaves de API_ → _Nova chave de API_.
4. Dê-lhe um nome descritivo (por exemplo `Shopware Connector`) e copie o valor gerado.

**Importante**: a chave de API só é apresentada uma vez. Se a perder, terá de gerar uma nova. Guarde-a num gestor de palavras-passe antes de fechar a janela.

## Configuração do lado do Shopware

### Preencher a ligação

Na administração do Shopware: _Definições → Sistema → Extensões → Df Odoo → Definições_, ou diretamente pelo menu lateral _Definições → Df Odoo → Definições_.

- **URL do Odoo**: URL completo da sua instância sem barra final, por exemplo `https://aminhaconta.odoo.com`.
- **Nome da base de dados**: visível no URL do Odoo depois de `?db=`, ou em _Definições → Técnico → Base de dados_.
- **Utilizador**: login do utilizador dedicado, geralmente o seu endereço de email.
- **Chave de API do Odoo**: valor copiado no passo anterior.
- **Tempo de espera**: 30 segundos por predefinição, suficiente na maioria dos casos.

### Testar a ligação

Clique no botão _Testar a ligação_ no canto superior direito. Se estiver tudo correto, uma notificação verde mostra a versão do Odoo e o identificador do utilizador (uid). Se a ligação falhar, a mensagem de erro devolvida pelo Odoo é apresentada tal como está.

**Conselho**: o teste de ligação também pode ser chamado a partir da consola para automatizar uma verificação:
`curl -X POST -H "Authorization: Bearer ADMIN_TOKEN" https://oseushopware.com/api/_action/df-odoo/test-connection`

## Direções de sincronização

Cada entidade tem um seletor independente: _desativado_, _Odoo → Shopware_ (pull), _Shopware → Odoo_ (push), ou _bidirecional_. Os valores predefinidos são:

- **Produtos**: bidirecional
- **Stock**: Odoo → Shopware (o Odoo é a fonte de verdade)
- **Clientes**: Shopware → Odoo
- **Encomendas**: Shopware → Odoo
- **Categorias**: desativado (a ativar manualmente consoante a sua organização)

## Sincronização dos produtos

### Estratégias de correspondência

São configuráveis três estratégias:

- **SKU** (recomendada): `productNumber` do Shopware ↔ `default_code` do Odoo.
- **ID do Odoo**: assenta apenas na tabela de mapeamento persistente. Útil se os seus SKU forem voláteis.
- **Código de barras** (EAN): `ean` do Shopware ↔ `barcode` do Odoo. Exige EAN preenchidos dos dois lados.

Uma vez ligados, dois produtos mantêm-se emparelhados através da tabela `df_odoo_mapping`, mesmo que o SKU mude depois.

### Pull a partir do Odoo

A tarefa agendada lê os `product.template` alterados desde a última execução (campo `write_date`) e cria ou atualiza os produtos correspondentes do lado do Shopware. Os campos sincronizados são: nome, SKU, preço de venda, preço de custo, descrição curta, descrição longa, peso, volume, estado ativo, categoria, impostos.

### Push para o Odoo

Os produtos principais do Shopware (com `parentId = null`) ativos são enviados para o Odoo como `product.template` do tipo _product_ (artigo armazenável). As variantes do Shopware são enviadas sob o seu produto principal.

**Deteção das alterações**: antes de cada escrita, um hash SHA-1 do conteúdo é comparado com o memorizado no mapeamento. Se nada mudou, a escrita é ignorada e a operação é registada como `skipped`. Isto evita saturar o Odoo nos crons sucessivos.

## Sincronização do stock

O stock é sempre puxado do Odoo (nunca o contrário). A cada 15 minutos, a tarefa agendada lê as variantes `product.product` em lotes de 100 por identificador de template principal, agrega `qty_available` ou `free_qty` (configurável globalmente) e atualiza depois o campo `stock` de cada produto Shopware numa única consulta DAL.

**qty_available vs free_qty**: o `qty_available` reflete o stock físico presente em armazém. O `free_qty` retira as quantidades já reservadas em encomendas não entregues. O _free_qty_ é geralmente preferível num site de venda, porque evita a sobrevenda.

## Sincronização das categorias

Desativada por predefinição. Ative-a se a sua árvore de categorias tiver de se manter sincronizada com a do Odoo. A hierarquia `parent_id` é preservada dos dois lados. Tal como nos produtos, um hash de conteúdo evita as escritas desnecessárias.

## Sincronização dos clientes

Os clientes do Shopware são enviados como `res.partner` do Odoo com:

- **Desduplicação por email**: antes de qualquer criação, é procurado um parceiro existente com o mesmo email e `parent_id = false`. Se existir, é atualizado em vez de duplicado.
- **company_type**: _company_ se o campo empresa da morada de facturação estiver preenchido, _person_ caso contrário.
- **Moradas filhas**: a morada de facturação predefinida é criada como parceiro filho com `type='invoice'`, e a morada de entrega como parceiro filho com `type='delivery'`.
- **Número de IVA intracomunitário**: transposto para o campo `vat` do parceiro principal.
- **País e região**: resolvidos por código ISO com cache em memória dentro do pedido.

## Sincronização das encomendas

### Em tempo real no checkout

Se a opção _Enviar cada encomenda logo na validação_ estiver ativa, um event subscriber escuta o `CheckoutOrderPlacedEvent` e envia de imediato a encomenda para o Odoo depois da finalização do checkout. O cliente é criado no Odoo se for necessário (através da sincronização de clientes), e a encomenda é depois criada como `sale.order` com:

- `partner_id` resolvido através do mapeamento de clientes.
- `order_line` em sintaxe de tuplo do Odoo: `[0, 0, {name, product_uom_qty, price_unit, product_id}]`.
- Uma linha adicional para os portes se o `totalPrice` do shipping for superior a zero.
- `company_id`, `warehouse_id`, `pricelist_id` segundo os valores predefinidos configurados.

**O checkout nunca é bloqueado**: se o Odoo estiver inacessível, o erro é registado em `df_odoo_log` e a encomenda será retomada nos 10 minutos seguintes pela tarefa agendada `df_odoo.order_sync`, que percorre as encomendas dos últimos 7 dias ainda não mapeadas.

### Filtro de estado

O filtro _Estado das encomendas_ permite restringir as encomendas enviadas:

- **Todas**: qualquer encomenda validada é enviada (recomendado em B2C com pagamento imediato).
- **Apenas pagas**: só as encomendas cujo estado de pagamento é _paid_ são enviadas. Evita enviar carrinhos abandonados com pagamento manual.
- **Pagas ou expedidas**: acrescenta às anteriores as encomendas expedidas antes do pagamento (B2B com prazos).

### Confirmação e fatura automáticas

Duas opções controlam o que acontece do lado do Odoo depois de a encomenda ser criada:

- **Confirmar a encomenda**: chama `action_confirm` na `sale.order`, que passa então diretamente ao estado _encomenda confirmada_ em vez de ficar como _orçamento_.
- **Criar a fatura**: chama `_create_invoices` para gerar de imediato uma fatura validada. O identificador da fatura criada é memorizado como mapeamento do tipo `invoice`.

## Multi sales channel

Todos os parâmetros da extensão podem ser substituídos por canal de venda. No topo da página _Definições_, o seletor nativo do Shopware permite alternar entre _Todos os canais_ e um canal específico.

Casos de uso típicos:

- Um canal B2C que envia para um Odoo principal e um canal B2B que envia para um Odoo distinto.
- Um canal de produção com direção _push_ e um canal de staging com direção _desativada_.
- Diferentes identificadores Odoo (warehouse, sales team, pricelist) consoante o canal.

## Tarefas agendadas

| Nome interno | Frequência | Ação |
| --- | --- | --- |
| `df_odoo.product_sync` | 1 hora | Pull e depois push de produtos segundo a direção configurada. O pull só examina as fichas alteradas desde -2 h. |
| `df_odoo.stock_sync` | 15 minutos | Pull do stock a partir do Odoo para todos os produtos já mapeados. |
| `df_odoo.customer_sync` | 1 hora | Push dos clientes ativos ainda não mapeados (100 no máximo por execução). |
| `df_odoo.order_sync` | 10 minutos | Push das encomendas dos últimos 7 dias ainda não mapeadas (50 no máximo por execução). |

Forçar a execução de uma tarefa a partir da consola:

```
sudo -u www-data setsid php bin/console scheduled-task:run-single df_odoo.product_sync
```

**Worker do Shopware**: para que as tarefas agendadas sejam acionadas automaticamente, o worker messenger do Shopware tem de estar a correr (cron `messenger:consume` ou tarefa systemd). Verifique em _Definições → Sistema → Fila de mensagens_ que a _scheduled_task_ é consumida regularmente.

## Módulo de administração

Aparece uma secção **Df Odoo** em _Definições → Extensões_ com quatro páginas.

### Painel

Contadores em direto (mapeamentos ativos por entidade, atividade das últimas 24 h por estado), botões de sincronização manual por entidade (pull e push), faixa de estado da ligação, lista dos erros recentes e atalhos para as outras páginas.

### Definições

Formulário completo com seletor de canal de venda. Botões _Testar a ligação_ e _Guardar_ na barra de ações.

### Registo

Todas as operações ficam registadas em `df_odoo_log` com o seu estado (_success_, _error_, _warning_, _skipped_), a sua direção, a entidade em causa, a duração em milissegundos e a mensagem completa. Filtros combináveis por estado, tipo de entidade e direção. Paginação do lado do servidor.

**Modo de depuração**: as operações _skipped_ só são escritas no registo se o modo de depuração estiver ativo nas definições. A usar pontualmente para diagnosticar um comportamento, e a desativar em produção para evitar saturar a tabela.

### Correspondências

Vista de leitura sobre a tabela `df_odoo_mapping` com pesquisa, filtro por tipo de entidade e ordenação por data da última sincronização. Prática para verificar se um dado produto está mesmo mapeado ao ID Odoo esperado.

## API REST de administração

Todos os endpoints exigem autenticação normal de administração (Bearer token).

| Método | Endpoint | Parâmetros |
| --- | --- | --- |
| POST | `/api/_action/df-odoo/test-connection` | `salesChannelId` (opcional) |
| POST | `/api/_action/df-odoo/sync/products` | `direction=pull\|push`, `salesChannelId` |
| POST | `/api/_action/df-odoo/sync/stock` | `salesChannelId` |
| POST | `/api/_action/df-odoo/sync/customers` | `salesChannelId` |
| POST | `/api/_action/df-odoo/sync/orders` | `salesChannelId`, `limit` (1-500) |
| POST | `/api/_action/df-odoo/sync/categories` | `direction=pull\|push` |
| GET | `/api/_action/df-odoo/stats` | — |
| GET | `/api/_action/df-odoo/logs` | `status`, `entityType`, `direction`, `page`, `perPage` |

Exemplo de chamada para forçar um push de produtos:

```
curl -X POST
  -H "Authorization: Bearer ADMIN_TOKEN"
  -d "direction=push"
  https://oseushopware.com/api/_action/df-odoo/sync/products
```

## Tabelas e dados guardados

A extensão cria duas tabelas MySQL:

- `df_odoo_mapping`: correspondências persistentes (identificador Shopware ↔ identificador Odoo) com hash de sincronização e payload opcional. Uma linha é única no par (tipo de entidade, identificador Shopware) e no par (tipo de entidade, identificador Odoo).
- `df_odoo_log`: registo das operações com estado, duração, mensagem, payload e identificador do canal de venda.

Nenhuma tabela normal do Shopware é alterada.

## Desinstalação

A partir da administração: _Extensões → As minhas extensões → Df Odoo → Desinstalar_.

Uma caixa de diálogo propõe duas opções:

- **Conservar os dados do utilizador** marcado: as tabelas `df_odoo_mapping` e `df_odoo_log` são preservadas, bem como os parâmetros de sistema. Prático em caso de reinstalação posterior.
- **Conservar os dados do utilizador** desmarcado: as duas tabelas são eliminadas (DROP TABLE) na desinstalação. A instância Odoo nunca é tocada.

## Resolução de problemas

### «Configuração Odoo incompleta» no teste de ligação

Um dos quatro campos obrigatórios (URL, base de dados, utilizador, chave de API) está vazio. Verifique que selecionou mesmo o canal de venda certo antes de guardar.

### «401 Unauthorized» ou «access denied»

A chave de API foi revogada do lado do Odoo, ou o utilizador não tem os direitos necessários no modelo visado. Regenere uma chave de API e verifique os direitos Odoo do utilizador (nomeadamente _Inventário → Utilizador_ e _Vendas → Administrador dos documentos_).

### «Ligação recusada» ou timeout

O URL do Odoo não está acessível a partir do servidor Shopware. Verifique que a firewall permite ligações de saída HTTPS para o domínio do Odoo. Aumente o tempo de espera se a sua instância Odoo for lenta a responder.

### Os produtos não se sincronizam

Verifique o registo (página _Registo_) à procura de entradas em erro. Ative o modo de depuração para registar também as operações _skipped_ e perceber se o hash de conteúdo faz com que nada mude realmente.

### As encomendas não saem no checkout

Verifique que a opção _Enviar cada encomenda logo na validação_ está marcada e que a direção _Encomendas_ está em _Shopware → Odoo_. Se o filtro de estado estiver em _Apenas pagas_ e o pagamento for assíncrono, é a tarefa agendada que envia a encomenda alguns minutos depois do recebimento.

## Limites conhecidos

- Os atributos de variantes do Odoo (`product.attribute`) ainda não são mapeados automaticamente. As variantes do Shopware são enviadas como produtos principais do Odoo (`product.template`). As variantes Odoo criadas manualmente mantêm-se corretamente ligadas através do seu template principal. Está prevista uma gestão nativa na versão 1.1.
- Os descontos de linha de encomenda são transpostos como `price_unit` ajustado, e não como `discount` do Odoo.
- Os métodos de pagamento e de expedição do Shopware não são mapeados para os `journal_id` do Odoo: são usados os valores predefinidos do Odoo.

## Suporte

Para qualquer questão, contacte a equipa DataFirefly através do formulário de contacto em [datafirefly.com](https://www.datafirefly.com/pt/contacto/). Lembre-se de juntar a exportação do registo (página _Registo_ → botão de exportação em breve) ou, no mínimo, uma captura da linha em erro, bem como a versão exata do Shopware, do PHP e do Odoo.
