CLI harness for Odoo 12 ERP — CRUD, modules, DB management, reports via XML-RPC. Requires: running Odoo 12 instance
Project description
cli-anything-odoo_12
CLI para Odoo 12 ERP — consulte dados, gerencie módulos, exporte relatórios e faça perguntas em linguagem natural, tudo pelo terminal.
Instalação
Em distros Linux modernas (PEP 668), a solução mais simples é usar pipx, que instala CLIs em ambientes isolados automaticamente:
# Instalar pipx (se ainda não tiver)
sudo apt install pipx
pipx ensurepath
# Instalar o CLI
pipx install cli-anything-odoo-12
# Atualizar para nova versão
pipx upgrade cli-anything-odoo-12
Alternativa com pip (em virtualenv ou sistemas sem PEP 668):
pip install cli-anything-odoo-12
Após instalar, o comando cli-anything-odoo_12 fica disponível no terminal.
Pré-requisitos
- Python 3.10+
- Odoo 12 rodando (acessível via rede, ex:
http://localhost:8069)
Início Rápido
1. Conectar ao Odoo
O CLI suporta dois protocolos de comunicação:
| Backend | Flag | Auth | Requisitos |
|---|---|---|---|
| REST (padrão) | --backend rest |
OAuth2 (client_credentials) | Módulo REST API instalado no Odoo |
| XML-RPC | --backend xmlrpc |
Usuário/senha | Nenhum (nativo do Odoo) |
Opção A: REST API (recomendado)
Requer configuração única do OAuth2:
Passo 1 — Criar Client OAuth2 no Odoo:
- Acesse Configurações > REST API > OAuth2
- Crie um novo client:
- Nome: ex. "CLI API"
- Tipo OAuth:
Client Credentials - Usuário: selecione o usuário Odoo que o client vai operar
- Copie o Client Key e Client Secret
Passo 2 — Configurar o CLI:
cli-anything-odoo_12 config setup-rest \
--client-id <CLIENT_KEY> \
--client-secret <CLIENT_SECRET> \
--url http://localhost:8069 \
--db mydb
Passo 3 — Verificar:
cli-anything-odoo_12 record search res.partner --domain "[('is_company','=',True)]" --limit 5
Opção B: XML-RPC (sem configuração extra)
# Conectar via XML-RPC e salvar credenciais
cli-anything-odoo_12 connect \
--url http://localhost:8069 --db mydb --user admin --password admin \
--backend xmlrpc --save
Após configurar (ambos os backends)
# As credenciais são reutilizadas automaticamente nos próximos comandos:
cli-anything-odoo_12 record search res.partner --limit 5
cli-anything-odoo_12 ask "empresas"
# Trocar backend por comando:
cli-anything-odoo_12 --backend xmlrpc record search res.partner --limit 5
# Ou passar credenciais por comando (sobrescreve config salva):
cli-anything-odoo_12 --url http://localhost:8069 --db mydb --user admin --password admin record search res.partner
2. Operações de Registros (CRUD)
# Buscar parceiros (somente empresas)
cli-anything-odoo_12 record search res.partner --domain "[('is_company','=',True)]" --fields name,email --limit 10
# Exemplo de saída:
# Found 10 record(s) in res.partner
# [0]
# id: 1
# name: My Company
# email: info@mycompany.com
# [1]
# id: 14
# name: Azure Interior
# email: azure@example.com
# Ler um registro específico
cli-anything-odoo_12 record read res.partner 1 --fields name,email,phone
# Criar registro
cli-anything-odoo_12 record create res.partner --values '{"name":"New Company","is_company":true}'
# Saída: Created res.partner record id=42
# Atualizar registro
cli-anything-odoo_12 record write res.partner 42 --values '{"phone":"+55 11 99999-0000"}'
# Excluir registro
cli-anything-odoo_12 record unlink res.partner 42
# Contar registros
cli-anything-odoo_12 record count res.partner --domain "[('is_company','=',True)]"
# Saída: res.partner: 15 record(s)
# Listar campos do modelo
cli-anything-odoo_12 record fields res.partner
# Saída: res.partner: 143 fields
3. Gerenciamento de Módulos
cli-anything-odoo_12 module list --installed
# Saída: Found 254 module(s)
cli-anything-odoo_12 module list --search sale
cli-anything-odoo_12 module info sale
cli-anything-odoo_12 module install sale
cli-anything-odoo_12 module update sale
4. Operações de Banco de Dados
cli-anything-odoo_12 db list
# Saída: Found 3 database(s)
# - erp-production
# - erp-staging
# - test_cli
cli-anything-odoo_12 db create new_db --lang pt_BR
cli-anything-odoo_12 db backup mydb /tmp/mydb_backup.zip
cli-anything-odoo_12 db restore new_db /tmp/mydb_backup.zip
cli-anything-odoo_12 db drop old_db --confirm
5. Relatórios
cli-anything-odoo_12 report list --model account.invoice
# Saída: Found 63 report(s)
cli-anything-odoo_12 report render account.report_invoice 42 --output invoice.pdf
# Saída: Report saved: invoice.pdf (45,231 bytes)
6. Exportação de Dados
# Exportar todos os parceiros para CSV
cli-anything-odoo_12 export csv res.partner --output partners.csv --fields name,email,phone
# Saída: Exported 920 records to partners.csv
# Exportar com filtro de domínio
cli-anything-odoo_12 export csv res.partner --output companies.csv --fields name,email --domain "[('is_company','=',True)]"
# Saída: Exported 15 records to companies.csv
# Exportar para JSON com limite
cli-anything-odoo_12 export json res.partner --output partners.json --fields name,email --limit 100
# Saída: Exported 100 records to partners.json
# Exportar para stdout (omitir --output)
cli-anything-odoo_12 export json res.partner --fields name --limit 3
7. Consulta em Linguagem Natural (NLQ)
O comando ask traduz perguntas em texto livre (PT-BR, EN, ES) em domínios de busca do Odoo usando padrões regex. Sem dependências externas ou LLM.
Consultas Simples
# Listar empresas
cli-anything-odoo_12 ask "liste todas as empresas"
# Exemplo de saída:
# ━━━ Empresas ━━━
# Consulta: res.company | 3 registro(s)
#
# ID Nome E-mail Telefone
# ─── ──────────────────── ────────────────── ──────────
# 1 The Cookiery info@cookiery.com (11) 3333-4444
# 3 Filial Centro centro@cookiery.com —
# 5 Filial Shopping shop@cookiery.com —
#
# Total: 3 registro(s)
# Buscar com filtros
cli-anything-odoo_12 ask "faturas de entrada pagas em janeiro/2024"
# Exemplo de saída:
# ━━━ Faturas de Entrada — Paid — Janeiro/2024 ━━━
# Consulta: account.invoice | 8 registro(s)
#
# ID Numero Parceiro Data Total (R$) Status
# ──── ──────── ───────────────── ────────── ────────── ──────
# 1042 INV/001 Fornecedor ABC 2024-01-05 15.230,00 paid
# 1043 INV/002 Fornecedor XYZ 2024-01-12 8.500,00 paid
# ...
#
# Total: 8 registro(s) | Soma: R$ 87.430,00
# Clientes ativos com limite
cli-anything-odoo_12 ask "clientes ativos" --limit 10
# Faturas de fornecedor (resolve para account.invoice com type=in_invoice)
cli-anything-odoo_12 ask "faturas de fornecedor abertas em janeiro/2026"
# Faturas de cliente (resolve para account.invoice com type=out_invoice)
cli-anything-odoo_12 ask "faturas de cliente pagas"
Filtro por Empresa (Multi-Company)
Em ambientes multi-company, o CLI filtra automaticamente pela empresa do usuário logado. Você pode sobrescrever com --company ou diretamente na query:
# Usar empresa do usuário logado (padrão — não precisa especificar nada)
cli-anything-odoo_12 ask "faturas abertas"
# Filtrar por empresa específica via flag --company (ID, nome ou CNPJ)
cli-anything-odoo_12 ask "faturas abertas" --company 3
cli-anything-odoo_12 ask "pedidos de venda" --company "The Cookiery"
cli-anything-odoo_12 ask "produtos" --company "12.345.678/0001-90"
# Filtrar por empresa diretamente na query (hint em linguagem natural)
cli-anything-odoo_12 ask "faturas da empresa The Cookiery"
cli-anything-odoo_12 ask "pedidos de compra da companhia 3"
# Exemplo de saída:
# ━━━ Faturas — Open ━━━
# Consulta: account.invoice | company_id=3 | 12 registro(s)
# ...
Prioridade de resolução do company_id:
- Hint na query (
"da empresa X") — maior prioridade - Flag
--companyna linha de comando - Valor salvo no config (
config set company_id 3) - Empresa do usuário logado — fallback padrão
Agrupamento entre Modelos (Consultas Analíticas)
Agrupe pedidos por categoria de produto ou produtos individuais — o CLI percorre automaticamente modelos relacionados (pedido > linha > produto > categoria).
# Vendas POS agrupadas por categoria de produto
cli-anything-odoo_12 ask "vendas do pos de janeiro/2026 agrupado por categoria de produto"
# Exemplo de saída:
# ━━━ Vendas do POS — Janeiro/2026 — por Categoria de Produto ━━━
# Consulta: pos.order | 229 itens de linha
#
# Categoria de Produto Itens Qtd Total (R$) %
# ──────────────────── ───── ──── ────────── ────
# Cookies 98 156 2.376,50 67.4%
# Bebidas 45 89 534,20 15.1%
# Salgados 38 62 312,80 8.9%
# Doces 28 45 198,34 5.6%
# Sem Categoria 20 32 106,00 3.0%
#
# Total: 229 itens | Qtd: 384 | Soma: R$ 3.527,84
# Vendas POS agrupadas por produto individual
cli-anything-odoo_12 ask "vendas do pos agrupado por produto"
# Faturas agrupadas por categoria de produto
cli-anything-odoo_12 ask "faturas agrupado por categoria de produto"
# Pedidos de compra agrupados por categoria de produto
cli-anything-odoo_12 ask "pedidos de compra agrupado por categoria de produto"
Agrupamentos entre Modelos Suportados
| Modelo | Chave de Agrupamento | Caminho de Travessia |
|---|---|---|
| pos.order | categoria de produto |
pos.order > pos.order.line > product.product > product.category |
| pos.order | categoria pos |
pos.order > pos.order.line > product.product > pos.category |
| pos.order | produto |
pos.order > pos.order.line > product.product |
| account.invoice | categoria de produto |
account.invoice > account.invoice.line > product.product > product.category |
| account.invoice | produto |
account.invoice > account.invoice.line > product.product |
| sale.order | categoria de produto |
sale.order > sale.order.line > product.product > product.category |
| sale.order | produto |
sale.order > sale.order.line > product.product |
| purchase.order | categoria de produto |
purchase.order > purchase.order.line > product.product > product.category |
Agrupamento por Campo Simples
# Vendas POS agrupadas por terminal de ponto de venda
cli-anything-odoo_12 ask "vendas do pos agrupado por pdv"
# Exemplo de saída:
# ━━━ Vendas do POS ━━━
# Consulta: pos.order | 50 registro(s)
#
# Grupo Qtd Total (R$) %
# ───────────────── ─── ────────── ────
# Loja Centro 28 4.520,00 65.2%
# Loja Shopping 22 2.410,00 34.8%
#
# Total: 50 registro(s) | Soma: R$ 6.930,00
Com Exportação
# Exportar para CSV
cli-anything-odoo_12 ask "faturas de entrada em janeiro/2024 e exporte para csv em /tmp/faturas.csv"
# Saída: ... Exportado para /tmp/faturas.csv
# Exportar para JSON
cli-anything-odoo_12 ask "empresas e exporte para json em /tmp/empresas.json"
# Consulta combinada com exportação
cli-anything-odoo_12 ask "faturas de entrada pagas em janeiro/2024 acima de R$ 5.000 e exporte para csv em /tmp/fat.csv"
Outros Exemplos de Consulta
# Aniversariantes de um mês específico
cli-anything-odoo_12 ask "aniversariantes de marco"
# Intervalo de datas
cli-anything-odoo_12 ask "faturas de 01/03 a 15/03"
# Datas relativas
cli-anything-odoo_12 ask "pedidos de compra este mes"
cli-anything-odoo_12 ask "faturas ultimo mes"
# Filtros por valor (formato BRL)
cli-anything-odoo_12 ask "faturas acima de R$ 10.000"
cli-anything-odoo_12 ask "pedidos de venda abaixo de 5000"
# Consultas em inglês
cli-anything-odoo_12 ask "invoices above 5000"
cli-anything-odoo_12 ask "active customers"
cli-anything-odoo_12 ask "paid invoices in january/2024"
# Consultas em espanhol
cli-anything-odoo_12 ask "facturas pagadas"
Aliases Suportados (Multilíngue)
| PT-BR | EN | ES | Odoo Model |
|---|---|---|---|
| empresas | companies | — | res.company |
| parceiros, contatos | partners, contacts | socios | res.partner |
| clientes | customers | — | res.partner (customer=True) |
| fornecedores | suppliers | proveedores | res.partner (supplier=True) |
| faturas, notas fiscais | invoices | facturas | account.invoice |
| faturas de fornecedor | supplier invoices | — | account.invoice (type=in_invoice) |
| faturas de cliente | customer invoices | — | account.invoice (type=out_invoice) |
| pedidos de venda | sale orders | pedido de venta | sale.order |
| pedidos de compra | purchase orders | orden de compra | purchase.order |
| produtos | products | — | product.product |
| pagamentos | payments | — | account.payment |
| vendas do pos, pedidos pos | — | — | pos.order |
| usuarios | users | — | res.users |
| aniversariantes | — | — | res.partner (birthday) |
Filtros Suportados
| Filtro | PT-BR | EN |
|---|---|---|
| Status | pagas, em aberto, rascunho, canceladas, confirmadas | paid, open, draft, cancelled, done |
| Type | de entrada, de saida | incoming, outgoing |
| Date | em janeiro/2024, este mes, ultimo mes | in january/2024, this month, last month |
| Range | de 01/03 a 15/03 | from 01/03 to 15/03 |
| Amount | acima de R$ 10.000, abaixo de 5000 | above 5000, below 1000 |
| Boolean | ativos, inativos, arquivados | active, inactive, archived |
| Document | CPF 123.456.789-00 | — |
| Group | agrupado por categoria de produto | grouped by product category |
| Export | exporte para csv em /tmp/f.csv | — |
| Limit | top 10, limitar a 5 | limit 10 |
| Company | da empresa X, da companhia Y | company X |
8. Gerenciamento de Configuração
# Mostrar configuração salva (senhas/tokens são mascarados)
cli-anything-odoo_12 config show
# Exemplo de saída:
# url: http://localhost:8069
# db: erp-thecookiery
# user: nexuz@nexuz.com.br
# password: adm***
# backend: rest
# grant_type: client_credentials
# client_id: vjVaBgp7...
# client_secret: 4EIwDzsN***
# access_token: eyJhbGci***
# token_expiry: 1742060400.0
# Excluir uma chave específica
cli-anything-odoo_12 config delete --key access_token
# Excluir toda a configuração
cli-anything-odoo_12 config delete
9. Saída JSON (para automação)
O flag --json pode ser usado globalmente ou por comando:
# Qualquer comando com --json produz saída legível por máquina
cli-anything-odoo_12 record search res.partner --limit 3 --json
# Exemplo de saída:
# {
# "model": "res.partner",
# "count": 3,
# "records": [
# {"id": 1, "name": "My Company", "email": "info@co.com"},
# ...
# ]
# }
cli-anything-odoo_12 ask "empresas" --json
# Saída JSON com agrupamento entre modelos
cli-anything-odoo_12 ask "vendas do pos agrupado por categoria de produto" --json
# Exemplo de saída:
# {
# "model": "pos.order",
# "title": "Vendas do POS",
# "group_by": "Categoria de Produto",
# "groups": [
# {"name": "Cookies", "count": 98, "qty": 156.0, "total": 2376.50, "pct": 67.4},
# ...
# ],
# "grand_count": 229,
# "grand_qty": 384.0,
# "grand_total": 3527.84
# }
cli-anything-odoo_12 module list --installed --json
cli-anything-odoo_12 db list --json
10. REPL Interativo
# Iniciar o REPL (execute sem subcomando)
cli-anything-odoo_12 --url http://localhost:8069 --db mydb --user admin --password admin
# Exemplo de sessão:
# cli-anything-odoo_12 v1.0.6
# Connected to http://localhost:8069 db=mydb uid=2
#
# odoo_12 [mydb] > record search res.partner --limit 5
# Found 5 record(s) in res.partner
# ...
#
# odoo_12 [mydb] > ask "faturas pagas em janeiro/2024"
# ━━━ Faturas — Paid — Janeiro/2024 ━━━
# ...
#
# odoo_12 [mydb] > quit
Flags Globais
| Flag | Efeito |
|---|---|
--json |
Saída JSON legível por máquina (disponível em todos os comandos) |
--version |
Exibe a versão do pacote instalado |
--url |
URL do servidor Odoo (sobrescreve config salva) |
--db |
Nome do banco de dados (sobrescreve config salva) |
--user |
Nome de usuário (sobrescreve config salva) |
--password |
Senha (sobrescreve config salva) |
--backend |
Protocolo de comunicação: rest (padrão) ou xmlrpc |
--company, -c |
Filtro de empresa no ask: ID, nome ou CNPJ (padrão: empresa do usuário logado) |
Arquitetura
cli_anything/odoo_12/
├── odoo_12_cli.py # Main CLI entry point (Click framework)
├── core/
│ ├── aliases.py # Multilingual model/status/type alias registry
│ ├── connection.py # Config management + backend factory (get_rpc)
│ ├── cross_group.py # Cross-model grouping engine
│ ├── database.py # Database operations (list, create, backup, etc.)
│ ├── export.py # CSV/JSON export
│ ├── formatters.py # Business-friendly output formatting
│ ├── module.py # Module management
│ ├── nlq.py # Natural Language Query parser (regex-based)
│ ├── record.py # CRUD operations
│ ├── report.py # Report generation
│ └── session.py # Undo/redo + command history
├── utils/
│ ├── odoo_backend_base.py # ABC OdooBackend (21 abstract methods) + config I/O
│ ├── odoo_backend.py # OdooRPC (XML-RPC) + backward-compat re-exports
│ ├── odoo_rest.py # OdooREST (REST API, OAuth2, urllib — zero deps)
│ └── repl_skin.py # Terminal UI (tables, colors, prompts)
└── tests/
├── TEST.md # Test plan + results
├── test_core.py # Unit tests (82 tests, no Odoo needed)
├── test_rest.py # REST backend unit tests (24 tests, mock HTTP)
└── test_full_e2e.py # E2E tests (27 tests, requires running Odoo)
Arquitetura de Backend
Todos os comandos funcionam de forma idêntica independentemente do backend. O OdooBackend ABC define 21 métodos
implementados por OdooRPC (XML-RPC) e OdooREST (REST API):
OdooBackend (ABC)
21 abstract methods
/ \
OdooRPC OdooREST
(xmlrpc.client) (urllib — REST API)
Built-in Odoo API OAuth2 + JSON/HTTP
O factory connection.py (get_rpc()) seleciona o backend com base na config salva ou no flag --backend.
REST é o padrão; XML-RPC está disponível como fallback via --backend xmlrpc.
OAuth2
O CLI utiliza o grant type client_credentials. O client OAuth2 é vinculado a um usuário no Odoo,
e a autenticação usa apenas client_id + client_secret.
O ciclo de vida do token é automático: tokens são persistidos em config.json, renovados na expiração
e re-autenticados em caso de falha (retry em 401).
Solução de Problemas
| Problema | Causa | Solução |
|---|---|---|
Connection refused |
Odoo offline ou URL errada | Verificar se Odoo esta rodando: curl http://localhost:8069/web/login |
Access Denied |
Credenciais invalidas | Verificar usuario/senha: cli-anything-odoo_12 connect --url ... --save |
OAuth2 authentication failed |
client_id/secret incorretos | Verificar OAuth2 client no Odoo (Settings > REST API > OAuth2) |
unauthorized_client |
OAuth Type do client incorreto | No Odoo, verificar se o OAuth Type esta como Client Credentials |
REST API error 500: AccessError |
Usuario REST sem permissoes suficientes | Alterar tipo do usuario para "Usuario Interno" (Settings > Users) |
Modelo nao reconhecido na query |
Alias NLQ nao existe | Usar alias suportado (ver tabela de aliases) ou record search <model> |
command not found |
CLI nao instalado | Executar pip install cli-anything-odoo-12 e verificar which cli-anything-odoo_12 |
404 on /api/* |
Modulo REST API nao instalado | Instalar modulo REST API no Odoo ou usar --backend xmlrpc |
| NLQ retorna 0 registros | Filtros muito restritivos | Simplificar a query (remover filtro de data) e testar incrementalmente |
| Export CSV vazio | Domain sem resultados | Testar a mesma query sem export primeiro para confirmar resultados |
Executando Testes
pip install -e ".[dev]"
# Testes unitários (não precisa de Odoo)
python3 -m pytest cli_anything/odoo_12/tests/test_core.py -v
# Testes do backend REST (não precisa de Odoo — usa mock HTTP)
python3 -m pytest cli_anything/odoo_12/tests/test_rest.py -v
# Testes E2E (requer Odoo rodando)
ODOO_URL=http://localhost:8069 ODOO_DB=mydb ODOO_USER=admin ODOO_PASSWORD=admin \
python3 -m pytest cli_anything/odoo_12/tests/test_full_e2e.py -v -s
# Todos os testes
CLI_ANYTHING_FORCE_INSTALLED=1 python3 -m pytest cli_anything/odoo_12/tests/ -v -s
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cli_anything_odoo_12-1.1.0.tar.gz.
File metadata
- Download URL: cli_anything_odoo_12-1.1.0.tar.gz
- Upload date:
- Size: 60.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc88cff1ecbcb8a30c72f5d1284045b2a09f2e6845d895d542ba729c314b36ca
|
|
| MD5 |
28d5548596202a8d0cfd67cdc1e1f7c4
|
|
| BLAKE2b-256 |
f8a1fe4b9fef227cff9f55aad8fbe8ece3e17ec9b146e9484d4bc66a5707701b
|
File details
Details for the file cli_anything_odoo_12-1.1.0-py3-none-any.whl.
File metadata
- Download URL: cli_anything_odoo_12-1.1.0-py3-none-any.whl
- Upload date:
- Size: 71.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b24de3ecea24cd66490c4f9af1ca54a657ebdf2c03fa56584f66080861017466
|
|
| MD5 |
9874a6ddf2153cbadf2492191d973dd1
|
|
| BLAKE2b-256 |
84c1863ca34968e7b15f6ecf05a70b09d3b422e587dc256ece01449a4751f41a
|