QUANDO NAO USAR ESTA SKILL
- Validar match NF x PO (este e Fase 2, anterior a consolidacao)
- Processar recebimento fisico com lotes/quality check (este e Fase 4, posterior)
- Operacoes financeiras como pagamentos ou reconciliacao de extratos
- Apenas consultar/rastrear documentos sem modificar POs
Conciliando Odoo PO
Skill para EXECUTAR operacoes de Split e Consolidacao de Pedidos de Compra no Odoo.
Contexto
Quando uma NF-e (DFe) chega com quantidades diferentes dos POs existentes, o sistema precisa:
- Criar um PO Conciliador que casa 100% com a NF
- Ajustar os POs originais para ficarem com o saldo restante
- Vincular o DFe ao PO Conciliador
Operacoes Suportadas
| Operacao |
Metodo |
Resultado |
| Simular consolidacao |
simular_consolidacao() |
Preview sem executar no Odoo |
| Executar consolidacao |
consolidar_pos() |
PO Conciliador criado + POs ajustados |
| Reverter consolidacao |
reverter_consolidacao() |
Desfaz acoes (best-effort) |
| Criar PO Conciliador |
_criar_po_conciliador() |
Duplica PO via copy() |
| Criar linha conciliador |
_criar_linha_po_conciliador() |
Duplica linha via copy() |
| Ajustar quantidade |
_ajustar_quantidade_linha() |
Reduz qtd no PO original |
| Vincular DFe ao PO |
_vincular_dfe_ao_po() |
Escreve dfe_id no PO |
| Cancelar PO vazio |
_cancelar_po() |
Cancela PO sem saldo |
Arquivo Principal
app/recebimento/services/odoo_po_service.py (1281 linhas)
Classe Principal
from app.recebimento.services.odoo_po_service import OdooPoService
service = OdooPoService()
Fluxo Completo de Consolidacao
ENTRADA:
- validacao_id (ValidacaoNfPoDfe com status='aprovado')
- pos_para_consolidar: [{'po_id': 123, 'po_name': 'PO00123'}, ...]
PASSO 1: Buscar fornecedor_id pelo CNPJ
→ odoo.search('res.partner', [('l10n_br_cnpj', '=', cnpj_formatado)])
PASSO 2: Criar PO Conciliador VAZIO
→ copy(PO de referencia) com overrides: partner_id, date_order, origin, state=draft, order_line=False
→ Fallback: se copy() copiar linhas, remove-las via unlink
PASSO 3: Para CADA item da NF com match:
→ Para cada MatchAlocacao (suporte multi-PO):
a) copy(linha de referencia) → nova linha no PO Conciliador com qtd_nf e preco_nf
b) write(linha original) → reduzir product_qty no PO original
PASSO 4: Confirmar PO Conciliador
→ execute_kw('purchase.order', 'button_confirm', [po_id])
PASSO 5: Vincular DFe ao PO Conciliador
→ write('purchase.order', po_id, {'dfe_id': dfe_id})
Modelos Locais Envolvidos
| Modelo |
Tabela |
Uso |
ValidacaoNfPoDfe |
validacao_nf_po_dfe |
Validacao principal (status, resultado) |
MatchNfPoItem |
match_nf_po_item |
Cada item da NF com match de PO |
MatchAlocacao |
match_alocacao |
Alocacao multi-PO (1 item NF → N POs) |
Modelos Odoo Envolvidos
| Modelo |
Campos Principais |
Operacoes |
purchase.order |
name, partner_id, date_order, origin, state, order_line, dfe_id |
copy, write, button_confirm, button_cancel |
purchase.order.line |
order_id, product_id, product_qty, price_unit, qty_received |
copy, write, unlink |
res.partner |
l10n_br_cnpj |
search |
Metodo de Conexao Odoo
from app.odoo.utils.connection import get_odoo_connection
odoo = get_odoo_connection()
odoo.authenticate()
# UNICO metodo generico disponivel:
resultado = odoo.execute_kw(modelo, metodo, args, kwargs)
# Helpers especificos (wrapper de execute_kw):
odoo.search(modelo, domain, limit=None)
odoo.read(modelo, ids, fields)
odoo.write(modelo, id_ou_ids, values)
odoo.create(modelo, values)
IMPORTANTE: NAO existe odoo.execute()
A classe OdooConnection (app/odoo/utils/connection.py) possui APENAS:
execute_kw(model, method, args, kwargs) - generico
search(), read(), write(), create() - helpers
NUNCA usar odoo.execute() — nao existe e causara AttributeError.
Cenarios de Uso
SPLIT (1 NF parcial de 1 PO)
PO Original: 500 un produto X
NF chegou: 400 un produto X
Resultado:
PO Original: 100 un (saldo)
PO Conciliador (NOVO): 400 un → vinculado a NF
CONSOLIDACAO (1 NF com itens de N POs)
PO-A: 500 un produto X
PO-B: 500 un produto Y
NF chegou: 400 X + 400 Y
Resultado:
PO-A: 100 un X (saldo)
PO-B: 100 un Y (saldo)
PO Conciliador (NOVO): 400 X + 400 Y → vinculado a NF
MULTI-PO SPLIT (1 item NF → N POs)
PO-A: 200 un produto X
PO-B: 300 un produto X
NF chegou: 450 un produto X
Resultado (via MatchAlocacao):
PO-A: 0 un (consumido total, pode ser cancelado)
PO-B: 50 un (saldo)
PO Conciliador: 200 X (do PO-A) + 250 X (do PO-B) = 450 X
Pre-requisitos para Consolidacao
- Validacao com
status='aprovado'
- MatchNfPoItem com
status_match='match' para cada item
- MatchAlocacao com
odoo_po_line_id preenchido para multi-PO
- Conexao Odoo funcional
Referencia Cruzada com Outras Skills
| Skill |
Quando usar em vez desta |
validacao-nf-po |
ANTES da consolidacao (match, de-para, divergencias) |
rastreando-odoo |
CONSULTAR documentos (nao executar) |
descobrindo-odoo-estrutura |
Explorar campos nao documentados |
executando-odoo-financeiro |
Operacoes financeiras (pagamentos, extratos) |
1---2name: conciliando-odoo-po3description: EXECUTA operacoes de conciliacao de Pedidos de Compra (PO) com DFe no Odoo: split, consolidacao, criacao de PO Conciliador, ajuste de saldos. USAR QUANDO: - Executar consolidacao de POs: "consolide os POs da NF 12345", "execute split do pedido" - Criar PO Conciliador: "crie PO conciliador", "duplique pedido de compra" - Ajustar saldo de PO: "reduza quantidade do PO", "ajuste saldo" - Reverter consolidacao: "reverta consolidacao", "desfaca split" - Depurar erro em consolidacao: "erro ao consolidar", "PO nao criado" - Entender fluxo split/consolidacao: "como funciona o split?", "o que e PO Conciliador?" NAO USAR QUANDO: - Apenas consultar/rastrear documentos sem modificar POs - Explorar campos de modelo Odoo desconhecido - Operacoes financeiras (pagamentos, extratos, reconciliacao) - Validar match NF x PO (este e processo anterior, Fase 2)4---5
6## QUANDO NAO USAR ESTA SKILL
7- Validar match NF x PO (este e Fase 2, anterior a consolidacao)
8- Processar recebimento fisico com lotes/quality check (este e Fase 4, posterior)
9- Operacoes financeiras como pagamentos ou reconciliacao de extratos
10- Apenas consultar/rastrear documentos sem modificar POs
11
12# Conciliando Odoo PO
13
14Skill para **EXECUTAR** operacoes de Split e Consolidacao de Pedidos de Compra no Odoo.
15
16## Contexto
17
18Quando uma NF-e (DFe) chega com quantidades diferentes dos POs existentes, o sistema precisa:
191. Criar um **PO Conciliador** que casa 100% com a NF
202. Ajustar os POs originais para ficarem com o **saldo restante**
213. Vincular o DFe ao PO Conciliador
22
23## Operacoes Suportadas
24
25| Operacao | Metodo | Resultado |
26|----------|--------|-----------|
27| Simular consolidacao | `simular_consolidacao()` | Preview sem executar no Odoo |
28| Executar consolidacao | `consolidar_pos()` | PO Conciliador criado + POs ajustados |
29| Reverter consolidacao | `reverter_consolidacao()` | Desfaz acoes (best-effort) |
30| Criar PO Conciliador | `_criar_po_conciliador()` | Duplica PO via copy() |
31| Criar linha conciliador | `_criar_linha_po_conciliador()` | Duplica linha via copy() |
32| Ajustar quantidade | `_ajustar_quantidade_linha()` | Reduz qtd no PO original |
33| Vincular DFe ao PO | `_vincular_dfe_ao_po()` | Escreve dfe_id no PO |
34| Cancelar PO vazio | `_cancelar_po()` | Cancela PO sem saldo |
35
36## Arquivo Principal
37
38`app/recebimento/services/odoo_po_service.py` (1281 linhas)
39
40## Classe Principal
41
42```python
43from app.recebimento.services.odoo_po_service import OdooPoService
44
45service = OdooPoService()
46```
47
48## Fluxo Completo de Consolidacao
49
50```
51ENTRADA:
52 - validacao_id (ValidacaoNfPoDfe com status='aprovado')
53 - pos_para_consolidar: [{'po_id': 123, 'po_name': 'PO00123'}, ...]
54
55PASSO 1: Buscar fornecedor_id pelo CNPJ
56 → odoo.search('res.partner', [('l10n_br_cnpj', '=', cnpj_formatado)])
57
58PASSO 2: Criar PO Conciliador VAZIO
59 → copy(PO de referencia) com overrides: partner_id, date_order, origin, state=draft, order_line=False
60 → Fallback: se copy() copiar linhas, remove-las via unlink
61
62PASSO 3: Para CADA item da NF com match:
63 → Para cada MatchAlocacao (suporte multi-PO):
64 a) copy(linha de referencia) → nova linha no PO Conciliador com qtd_nf e preco_nf
65 b) write(linha original) → reduzir product_qty no PO original
66
67PASSO 4: Confirmar PO Conciliador
68 → execute_kw('purchase.order', 'button_confirm', [po_id])
69
70PASSO 5: Vincular DFe ao PO Conciliador
71 → write('purchase.order', po_id, {'dfe_id': dfe_id})
72```
73
74## Modelos Locais Envolvidos
75
76| Modelo | Tabela | Uso |
77|--------|--------|-----|
78| `ValidacaoNfPoDfe` | `validacao_nf_po_dfe` | Validacao principal (status, resultado) |
79| `MatchNfPoItem` | `match_nf_po_item` | Cada item da NF com match de PO |
80| `MatchAlocacao` | `match_alocacao` | Alocacao multi-PO (1 item NF → N POs) |
81
82## Modelos Odoo Envolvidos
83
84| Modelo | Campos Principais | Operacoes |
85|--------|-------------------|-----------|
86| `purchase.order` | name, partner_id, date_order, origin, state, order_line, dfe_id | copy, write, button_confirm, button_cancel |
87| `purchase.order.line` | order_id, product_id, product_qty, price_unit, qty_received | copy, write, unlink |
88| `res.partner` | l10n_br_cnpj | search |
89
90## Metodo de Conexao Odoo
91
92```python
93from app.odoo.utils.connection import get_odoo_connection
94
95odoo = get_odoo_connection()
96odoo.authenticate()
97
98# UNICO metodo generico disponivel:
99resultado = odoo.execute_kw(modelo, metodo, args, kwargs)
100
101# Helpers especificos (wrapper de execute_kw):
102odoo.search(modelo, domain, limit=None)
103odoo.read(modelo, ids, fields)
104odoo.write(modelo, id_ou_ids, values)
105odoo.create(modelo, values)
106```
107
108## IMPORTANTE: NAO existe `odoo.execute()`
109
110A classe `OdooConnection` (app/odoo/utils/connection.py) possui APENAS:
111- `execute_kw(model, method, args, kwargs)` - generico
112- `search()`, `read()`, `write()`, `create()` - helpers
113
114**NUNCA usar `odoo.execute()`** — nao existe e causara AttributeError.
115
116## Cenarios de Uso
117
118### SPLIT (1 NF parcial de 1 PO)
119```
120PO Original: 500 un produto X
121NF chegou: 400 un produto X
122
123Resultado:
124 PO Original: 100 un (saldo)
125 PO Conciliador (NOVO): 400 un → vinculado a NF
126```
127
128### CONSOLIDACAO (1 NF com itens de N POs)
129```
130PO-A: 500 un produto X
131PO-B: 500 un produto Y
132NF chegou: 400 X + 400 Y
133
134Resultado:
135 PO-A: 100 un X (saldo)
136 PO-B: 100 un Y (saldo)
137 PO Conciliador (NOVO): 400 X + 400 Y → vinculado a NF
138```
139
140### MULTI-PO SPLIT (1 item NF → N POs)
141```
142PO-A: 200 un produto X
143PO-B: 300 un produto X
144NF chegou: 450 un produto X
145
146Resultado (via MatchAlocacao):
147 PO-A: 0 un (consumido total, pode ser cancelado)
148 PO-B: 50 un (saldo)
149 PO Conciliador: 200 X (do PO-A) + 250 X (do PO-B) = 450 X
150```
151
152## Pre-requisitos para Consolidacao
153
1541. Validacao com `status='aprovado'`
1552. MatchNfPoItem com `status_match='match'` para cada item
1563. MatchAlocacao com `odoo_po_line_id` preenchido para multi-PO
1574. Conexao Odoo funcional
158
159## Referencia Cruzada com Outras Skills
160
161| Skill | Quando usar em vez desta |
162|-------|--------------------------|
163| `validacao-nf-po` | ANTES da consolidacao (match, de-para, divergencias) |
164| `rastreando-odoo` | CONSULTAR documentos (nao executar) |
165| `descobrindo-odoo-estrutura` | Explorar campos nao documentados |
166| `executando-odoo-financeiro` | Operacoes financeiras (pagamentos, extratos) |