Claude-skill-registry integracao-odoo
Skill para CRIAR novas integracoes com Odoo. Cobre lancamento de CTes, despesas extras e documentos fiscais seguindo o processo de 16 etapas. Use quando precisar IMPLEMENTAR novos fluxos de lancamento ou MODIFICAR existentes. Para CONSULTAS use a skill rastreando-odoo.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/integracao-odoo" ~/.claude/skills/majiayu000-claude-skill-registry-integracao-odoo && rm -rf "$T"
skills/data/integracao-odoo/SKILL.mdIntegracao Odoo - Sistema de Fretes
ATENCAO: Esta skill eh para DESENVOLVIMENTO (criar/modificar integracoes). Para CONSULTAS e rastreamento de fluxos, use a skill
.rastreando-odoo
Skill de desenvolvimento que documenta o processo completo de integracao com o Odoo ERP para lancamento de documentos fiscais (CTe) no sistema de fretes.
Quando Usar Este Skill
- Implementar novo fluxo de lançamento de documento fiscal no Odoo
- Criar integração para novo tipo de despesa/frete
- Modificar processo existente de lançamento
- Debugar problemas em lançamentos Odoo
- Entender o fluxo de 16 etapas
Arquitetura da Integração
Modelos Odoo Envolvidos
| Modelo | Descrição | Uso |
|---|---|---|
| Documento Fiscal Eletrônico | Busca e configuração inicial |
| Linhas do DFe | Produto e conta analítica |
| Pagamentos do DFe | Vencimento |
| Pedido de Compra | PO gerado do DFe |
| Fatura/Invoice | Documento final |
IDs Fixos do Odoo (Ambiente Produção)
PRODUTO_SERVICO_FRETE_ID = 29993 # Produto "SERVICO DE FRETE" CONTA_ANALITICA_LOGISTICA_ID = 1186 # Centro de custo Logística TEAM_LANCAMENTO_FRETE_ID = 119 # Equipe de lançamento PAYMENT_PROVIDER_TRANSFERENCIA_ID = 30 # Forma pagamento COMPANY_NACOM_GOYA_CD_ID = 4 # Empresa PICKING_TYPE_CD_RECEBIMENTO_ID = 13 # Tipo recebimento CD
As 16 Etapas do Lançamento
Fase 1: Configuração do DFe (Etapas 1-5)
Etapa 1: Buscar DFe pela chave de acesso (44 dígitos) Modelo: l10n_br_ciel_it_account.dfe Ação: search_read Validação: status deve ser '04' (PO) Etapa 2: Atualizar data de entrada e payment_reference Campos: l10n_br_date_in, payment_reference Etapa 3: Definir tipo_pedido = 'servico' Etapa 4: Atualizar linha com produto SERVICO DE FRETE Modelo: l10n_br_ciel_it_account.dfe.line Campos: product_id, analytic_distribution Etapa 5: Atualizar vencimento Modelo: l10n_br_ciel_it_account.dfe.pagamento Campo: date_due
Fase 2: Purchase Order (Etapas 6-10)
Etapa 6: Gerar Purchase Order Método: action_gerar_po_dfe Etapa 7: Configurar PO Campos: team_id, payment_provider_id, picking_type_id Etapa 8: (Pulada) Impostos calculados automaticamente Etapa 9: Confirmar PO Método: button_confirm Etapa 10: Aprovar PO (se necessário) Método: button_approve Condição: state == 'to approve'
Fase 3: Invoice (Etapas 11-16)
Etapa 11: Criar Invoice Método: action_create_invoice Etapa 12: Atualizar impostos Método: _compute_tax_totals Etapa 13: Configurar Invoice Campos: invoice_date, payment_reference Etapa 14: Recalcular impostos Etapa 15: Confirmar Invoice Método: action_post Etapa 16: Atualizar registro local Campos: odoo_dfe_id, odoo_purchase_order_id, odoo_invoice_id, lancado_odoo_em, lancado_odoo_por, status
Estrutura do Service de Lançamento
Campos Necessários no Modelo Local
Para qualquer entidade que será lançada no Odoo, adicionar:
# Integração Odoo odoo_dfe_id = db.Column(db.Integer, nullable=True, index=True) odoo_purchase_order_id = db.Column(db.Integer, nullable=True) odoo_invoice_id = db.Column(db.Integer, nullable=True) lancado_odoo_em = db.Column(db.DateTime, nullable=True) lancado_odoo_por = db.Column(db.String(100), nullable=True) # Status deve incluir 'LANCADO_ODOO' status = db.Column(db.String(20), default='PENDENTE', nullable=False, index=True)
Estrutura do Service
class LancamentoXxxOdooService(LancamentoOdooService): """ Service para lançar [entidade] no Odoo. Herda de LancamentoOdooService e adapta para [entidade]. """ def lancar_xxx_odoo(self, xxx_id: int, data_vencimento: date = None) -> Dict[str, Any]: """ Executa lançamento completo no Odoo Returns: Dict com: sucesso, mensagem, dfe_id, purchase_order_id, invoice_id, etapas_concluidas, auditoria, erro """ # 1. Validações iniciais # 2. Buscar CTe vinculado # 3. Conectar no Odoo # 4. Executar 16 etapas # 5. Atualizar registro local # 6. Retornar resultado
Auditoria
Cada etapa deve ser registrada na tabela
lancamento_frete_odoo_auditoria:
LancamentoFreteOdooAuditoria( frete_id=None, # ou ID do frete despesa_extra_id=None, # ou ID da despesa cte_id=cte_id, chave_cte=chave_cte, etapa=numero_etapa, etapa_descricao="Descrição da etapa", modelo_odoo='modelo.odoo', metodo_odoo='nome_metodo', # se aplicável acao='search_read|write|execute_method|skip', status='SUCESSO|ERRO', mensagem="Mensagem descritiva", tempo_execucao_ms=tempo_ms, dfe_id=dfe_id, purchase_order_id=po_id, invoice_id=invoice_id )
Pré-requisitos para Lançamento
- CTe deve existir no Odoo com status '04' (PO)
- CTe deve estar vinculado ao registro local
- Data de vencimento deve estar definida
- Usuário autenticado no sistema
Tratamento de Erros e Rollback
def _rollback_xxx_odoo(self, xxx_id: int, etapas_concluidas: int) -> bool: """ Limpa campos Odoo em caso de erro (se não completou 16 etapas) """ if status != 'LANCADO_ODOO' or etapas_concluidas < 16: xxx.odoo_dfe_id = None xxx.odoo_purchase_order_id = None xxx.odoo_invoice_id = None xxx.lancado_odoo_em = None xxx.lancado_odoo_por = None xxx.status = 'status_anterior'
Exemplos Reais de Implementacao
Exemplo 1: Lancamento de Frete (Referencia Principal)
Arquivos:
- Service:
app/fretes/services/lancamento_odoo_service.py - Route:
-app/fretes/routes.pylancar_frete_odoo() - Model:
- classeapp/fretes/models.pyFrete
Fluxo resumido:
# Route recebe requisicao @fretes_bp.route('/api/fretes/<int:frete_id>/lancar-odoo', methods=['POST']) def lancar_frete_odoo(frete_id): service = LancamentoFreteOdooService() resultado = service.lancar_frete_odoo( frete_id=frete_id, data_vencimento=data_venc, usuario=current_user.nome ) return jsonify(resultado) # Service executa 16 etapas class LancamentoFreteOdooService(LancamentoOdooService): def lancar_frete_odoo(self, frete_id, data_vencimento, usuario): # 1. Busca frete no banco local frete = Frete.query.get(frete_id) # 2. Valida pre-requisitos if not frete.chave_cte: raise ValueError("Frete sem CTe vinculado") # 3. Executa 16 etapas no Odoo resultado = self._executar_16_etapas(frete.chave_cte, data_vencimento) # 4. Atualiza registro local frete.odoo_invoice_id = resultado['invoice_id'] frete.status = 'LANCADO_ODOO' db.session.commit()
Exemplo 2: Lancamento de Despesa Extra
Arquivos:
- Service:
app/fretes/services/lancamento_despesa_odoo_service.py - Route:
-app/fretes/routes.pylancar_despesa_odoo() - Model:
- classeapp/fretes/models.pyDespesaExtra
Diferenca em relacao ao Frete:
# DespesaExtra pode ter transportadora diferente do Frete pai # Por isso tem campo transportadora_id proprio class LancamentoDespesaOdooService(LancamentoOdooService): def lancar_despesa_odoo(self, despesa_id, data_vencimento, usuario): despesa = DespesaExtra.query.get(despesa_id) # Usa CTe da despesa (pode ser diferente do frete) chave_cte = despesa.chave_cte # Usa transportadora da despesa (se definida) ou do frete transportadora = despesa.transportadora or despesa.frete.transportadora # Resto do fluxo igual ao Frete
Campos adicionados no modelo DespesaExtra:
# Em app/fretes/models.py class DespesaExtra(db.Model): # ... campos existentes ... # Campos de integracao Odoo (adicionados para lancamento) odoo_dfe_id = db.Column(db.Integer, nullable=True, index=True) odoo_purchase_order_id = db.Column(db.Integer, nullable=True) odoo_invoice_id = db.Column(db.Integer, nullable=True) lancado_odoo_em = db.Column(db.DateTime, nullable=True) lancado_odoo_por = db.Column(db.String(100), nullable=True) # Transportadora alternativa (se diferente do Frete pai) transportadora_id = db.Column(db.Integer, db.ForeignKey('transportadoras.id'), nullable=True)
Padrao de Frontend para Lancamento
Modal de progresso (usado em ambos):
<!-- Modal mostra progresso das 16 etapas --> <div class="modal" id="modalProgresso"> <div class="progress-bar"> <div class="progress" style="width: 0%"></div> </div> <div id="etapaAtual">Iniciando...</div> </div>
JavaScript AJAX:
function lancarOdoo(id, tipo) { const url = tipo === 'frete' ? `/api/fretes/${id}/lancar-odoo` : `/api/despesas/${id}/lancar-odoo`; fetch(url, { method: 'POST', body: JSON.stringify(dados) }) .then(response => response.json()) .then(resultado => { if (resultado.sucesso) { atualizarUI(resultado); } else { mostrarErro(resultado.erro, resultado.etapas_concluidas); } }); }
Checklist para Nova Integração
- Adicionar campos Odoo no modelo (
,odoo_dfe_id
, etc.)odoo_purchase_order_id - Adicionar status
no modeloLANCADO_ODOO - Criar script de migração para novos campos
- Criar Service herdando de
LancamentoOdooService - Implementar método
com 16 etapaslancar_xxx_odoo() - Implementar método
_rollback_xxx_odoo() - Criar route POST para lançamento
- Criar route GET para auditoria
- Atualizar template com botão de lançamento e modal
- Adicionar JavaScript para chamada AJAX com progresso
- Testar em ambiente de desenvolvimento
- Documentar no CLAUDE.md
Conexão com Odoo
from app.odoo.utils.connection import get_odoo_connection odoo = get_odoo_connection() if not odoo.authenticate(): raise Exception("Falha na autenticação com Odoo") # Operações disponíveis: odoo.search_read(modelo, filtros, fields, limit) odoo.read(modelo, ids, fields) odoo.write(modelo, ids, valores) odoo.execute_method(modelo, metodo, args)
Guidelines
- SEMPRE registrar auditoria de cada etapa
- NUNCA pular etapas sem registrar na auditoria (usar status 'skip')
- SEMPRE implementar rollback para limpeza em caso de erro
- SEMPRE validar status do DFe antes de iniciar (deve ser '04')
- NUNCA lançar documento que já foi lançado (verificar
)odoo_invoice_id - SEMPRE usar transação para atualizar registro local no final
- SEMPRE capturar tempo de execução de cada etapa para diagnóstico
Relacionado
| Skill | Uso |
|---|---|
| rastreando-odoo | Para CONSULTAS e rastreamento de fluxos (NF, PO, SO, titulos, conciliacoes) |
| descobrindo-odoo-estrutura | Para descobrir campos/modelos nao mapeados |
| gerindo-expedicao | Para consultas de carteira, separacoes e estoque |
Templates Disponiveis
Os templates em
resources/ auxiliam na criacao de novas integracoes:
| Template | Descricao |
|---|---|
| Campos SQLAlchemy para integracao Odoo |
| Estrutura base do Service de lancamento |
| Script de migracao para novos campos |
| Routes Flask para lancamento e auditoria |