Histórico — Integração Pipedrive → Omie¶
Atualizado: 2026-07-08 · por: sessão manual · validação prod + fuso horário · rev: 3 Cronologia de mudanças, bugs encontrados e fixes. Cada entrada tem data, contexto, e (quando aplicável) link pra execução de referência.
2026-04-29 — Habilitação de fluxo PF (Fase 1)¶
Pedido: Bepex queria que orçamentos com CPF (pessoa física) também subissem pra Omie. Até então, eram descartados silenciosamente no [73] UpdateDeal por falta de CNPJ.
Investigação preliminar:
- Analisei o cenário completo (44 módulos) e documentei em PIPEDRIVE_TO_OMIE_INTEGRACAO.md.
- Confirmei que orçamentos PF do FlowTech trazem cliente.cpf preenchido e cliente.cnpj vazio (separados).
- Confirmei que a Omie aceita CPF no mesmo IncluirCliente (campo pessoa_fisica é "preenchimento automático" pela quantidade de dígitos).
- Confirmei que a "Org-falsa-pra-PF" do padrão Bepex no Pipedrive tem address_* subcampos populados (autocomplete Google) — mesmo formato do PJ.
- Decisão arquitetural com Andrei: usar a Org-falsa-pra-PF pra reaproveitar 100% do caminho do [78] GetOrganization existente.
Mudanças aplicadas (PATCH em 22:32 BRT):
| Módulo | Mudança |
|---|---|
[73] filter |
Tem cnpj? → Tem cnpj OR cpf? |
[54] value |
ifempty(cnpj; cpf) antes do strip de pontos/traços/barras |
[33] filter (🚨 ERRO ARQUITETURAL) |
Adicionado PJ apenas (tem cnpj) — esperava "skip pra PF" mas abortou toda a rota |
[31] mapper |
cnpj_cpf: ifempty(cnpj; cpf), razao_social triplo fallback (Pipedrive Org → DateCode → cliente.nome), novo nome_fantasia (obrigatório NF-e), novo contribuinte: "S"/"N" condicional, fallback estado pra 78.address_admin_area_level_1 |
Validação preguiçosa (falha minha): - Testei via clone (cenário 4706443 com webhook próprio) com Wellington Martins Gonçalves (deal 74183, orçamento 30666, ATARES). - Make marcou Success. - NÃO conferi se o pedido REALMENTE existia no Omie. Reportei como funcional.
Avisos enviados: - WhatsApp Bepex pra Daiane (conv 94), Andrei (conv 30) e Enríco (conv 56). Pedido pra conferirem no dia seguinte.
2026-04-30 a 2026-05-04 — Período do bug silencioso¶
Execuções no cenário 2912018 após PATCH:
| Data/hora (BRT) | Ops | Status Make | Realidade no Omie |
|---|---|---|---|
| 30/04 08:30 | 66 | success | ? |
| 30/04 08:32 | 20 | success | ? |
| 30/04 11:51 | 60 | success | ? |
| 30/04 14:28 | 38 | success | ? |
| 30/04 17:11 | 29 | success (PJ ATARES) | ✅ pedido 457 criado |
| 04/05 08:44 | 19 | success (PJ ONIX) | ✅ pedido criado |
| 04/05 14:59 | 26 | success | ? |
| 04/05 15:02 | 48 | success | ? |
| 04/05 16:48 | 25 | success (PF ATARES Wellington) | ❌ pedido NÃO criado (Omie 500) |
Reporte do Andrei no WhatsApp Bepex (conv 30): - 30/04 16:09 — "Fui testar agora" + "Deu erro" + screenshot do FlowTech "Ocorreu um erro na integração com OMIE" - 04/05 09:00 — "Bom dia Rafa" + "Conseguiu ver o que pode ser o erro?" + "Nenhum pedido está subindo mais"
2026-05-04 16:48 BRT — Diagnóstico do bug¶
Investigação:
1. Confirmei via API que as 4 mudanças do PATCH ainda estavam aplicadas (ninguém reverteu).
2. Abri a execução 84ded951f8a14a38943e4cce78cdd6e8 (run mais recente: PF Wellington tentativa do Andrei).
3. Vi que [33] foi filtrado (esperado) MAS [31] IncluirCliente também não rodou — saltou direto de [33] pra [55] GetVariables → [57] AdicionarPedido.
4. Abri o output do [57]: status 500, body {"status":"error","message":"Invalid JSON object"}.
5. Confirmei o request: codigo_cliente enviado com valor null (variável código cliente omie nunca foi setada porque [31] e [36/39] não rodaram).
Causa raiz identificada:
Filter em módulo do Make aborta TODA a rota sequencial seguinte, não só pula o módulo filtrado.
Quando o [33] DateCode tem filter PJ apenas e o bundle não passa (PF), o Make não processa nenhum dos módulos depois dele NA MESMA ROTA — incluindo [31] IncluirCliente, [38] Router, [36/39] SetVar do código cliente omie.
Como o [55] GetVariables (que está em outra sub-rota) tenta ler código cliente omie que nunca foi setado, ele retorna vazio. [57] AdicionarPedido então monta payload com codigo_cliente: null/undefined. Omie devolve 500 "Invalid JSON object". Make marca como "completed" porque não tem error handler configurado → success silencioso.
Pra PJ funcionou esse tempo todo porque [33] passa o filter, [31] roda normalmente, código cliente omie é setado.
2026-05-04 — Plano de fix e escolha (consulta ao Rafael)¶
3 opções avaliadas:
| Opção | O que faz | Problema |
|---|---|---|
A — Inverter ordem [31] e [33] |
[31] IncluirCliente roda antes de [33] |
Pra PJ, telefone/endereço da DateCode ainda não foram fetched → regressão (campos vazios no IncluirCliente) |
B — Remover filter do [33] + error handler "Resume" |
DateCode roda pra PF, falha, handler "Resume" continua o flow | Rafael avisou que error handler "Resume" do Make é frágil — não confiar |
C — Remover filter do [33] + tornar tipoPessoa condicional |
DateCode roda pra ambos com tipoPessoa correto |
Depende de DateCode aceitar tipoPessoa: "PF" (não testado) |
Rafael instruiu: testar Opção C primeiro; se falhar, partir pra Opção D (bifurcar em duas rotas PJ vs PF separadas).
2026-05-04 18:20 BRT — Validação da Opção C no clone¶
Mudanças no clone 4706443:
- Removido filter PJ apenas (tem cnpj) do [33]
- Body do [33]: "tipoPessoa": "{{if(9.data.cliente.cnpj; "PJ"; "PF")}}"
Disparei webhook pra Wellington PF. Execução 5c787354b60b4524836f7f638a6c14c8:
- ✅ [33] DateCode rodou em 1.1s com tipoPessoa: "PF" — DateCode aceita PF e retorna dados
- ✅ [31] IncluirCliente rodou em 0.8s
- ✅ [57] AdicionarPedido retornou status 200 com codigo_pedido: 11050337175, numero_pedido: 0000000000000459, "Pedido incluído com Sucesso!"
Opção C validada.
2026-05-04 18:23 BRT — Fix aplicado em produção¶
PATCH no cenário 2912018 com as 2 mudanças (sem filter, tipoPessoa condicional).
Clone 4706443 parado pra economizar credits.
WhatsApp pro Andrei (conv 30): - Aviso de que o fix foi aplicado - Pedido pra ele rodar próximo orçamento PF pelo FlowTech e reportar - Aviso de que os PF tentados entre 30/04 e 04/05 ficaram zumbis e precisam ser disparados de novo
2026-05-04 21:03 BRT — Re-validação em produção via Replay run¶
Pedido do Rafael: repetir o teste do Wellington direto na produção (não no clone) pra ter certeza.
Replay run da execução 84ded951f8a14a38943e4cce78cdd6e8 (a antiga problemática).
Nova execução 672dabc96d55477db409f40eacef89d9:
- 19 ops, 9.8s, success
- ✅ [33] DateCode — 1.2s
- ✅ [31] IncluirCliente — 0.6s
- ✅ [57] AdicionarPedido — 2.4s, status 200, codigo_pedido: 11050367661, numero_pedido: 0000000000000460, "Pedido incluído com Sucesso!"
Pedido 460 criado em produção no Omie ATARES com cliente PF Wellington Martins Gonçalves. Fix validado em produção.
2026-06-19 — Fix: campo estado passava nome completo do estado para a Omie (fallback Pipedrive)¶
Bug reportado: execução de referência a8ed2bdb4f65491eba87269b3c7307e5 (produção, 18/jun) — campo estado chegava na Omie como "Espírito Santo" (nome completo) quando o fallback era o campo address_admin_area_level_1 do Pipedrive. A Omie só aceita sigla UF (2 letras).
Causa raiz: o campo estado no [31] tinha ifempty(33.data[].enderecos[].uf; 78.address_admin_area_level_1). O DateCode retorna uf como sigla ("ES") — funcionava. Mas quando o DateCode não retornava uf (ou retornava vazio), o fallback do Pipedrive trazia o nome completo do estado — a Omie rejeita.
Fix aplicado: substituído o fallback por switch() com mapeamento dos 27 estados (26 + DF). DateCode continua prioritário via ifempty. O último argumento do switch() é passthrough (78.address_admin_area_level_1 literal) para valores inesperados.
"estado":"{{ifempty(33.data[].enderecos[].uf; switch(78.address_admin_area_level_1;
"Acre";"AC"; "Alagoas";"AL"; "Amapá";"AP"; "Amazonas";"AM"; "Bahia";"BA";
"Ceará";"CE"; "Distrito Federal";"DF"; "Espírito Santo";"ES"; "Goiás";"GO";
"Maranhão";"MA"; "Mato Grosso";"MT"; "Mato Grosso do Sul";"MS"; "Minas Gerais";"MG";
"Pará";"PA"; "Paraíba";"PB"; "Paraná";"PR"; "Pernambuco";"PE"; "Piauí";"PI";
"Rio de Janeiro";"RJ"; "Rio Grande do Norte";"RN"; "Rio Grande do Sul";"RS";
"Rondônia";"RO"; "Roraima";"RR"; "Santa Catarina";"SC"; "São Paulo";"SP";
"Sergipe";"SE"; "Tocantins";"TO"; 78.address_admin_area_level_1))}}"
Processo:
- Fix testado primeiro no clone 4706443 (reativado)
- Webhook disparado com Wellington PF (deal 74183, ATARES): execução baefbc221f2f4f69842413b8b709141f, 19 ops, success
- Request body do [31] confirmado: "estado": "RJ" ✅
- PATCH aplicado em produção 2912018 às 11:07 BRT
- GET de verificação confirmou switch() salvo no blueprint
- Clone 4706443 desativado
- Andrei notificado via WhatsApp (conv 30, msg 2656054)
2026-07-03 — Fix: módulo 90 bloqueava módulo 31 quando UF estava preenchida (Router 52)¶
Contexto: Dois orçamentos não tinham subido pra Omie: - Orç. 32730 — Metalurgica Felix LTDA (PR), deal 74161, org 33101 - Orç. 32691 — BRAXON SOLUCOES INDUSTRIAIS (SC), deal 76809, org 36389
Ambos tinham address_admin_area_level_1 vazio no Pipedrive (corrigido via geocodificação Google em sessão anterior). Após o preenchimento da UF, os replays ainda falhavam.
Investigação:
- Advanced Log: m31 (IncluirCliente) não aparecia — bundle pulava de m33 direto pra m55/m57.
- Trace: na rota 0 do Router 52, o flow era [m33, m90, m31, m38]. Módulo 90 ("⚠️ Alerta UF Vazia") tem filtro address_admin_area_level_1 empty — só produz bundle quando UF está ausente.
- Com UF preenchida, m90 é filtrado → não produz bundle → m31 (sequencial depois de m90) não recebe nada → não roda → código cliente omie nunca é setado → m57 bloqueado pelo filter length(código cliente omie) > 0.
Causa raiz:
M31 dependia de m90 como elo sequencial para receber o bundle. M90 só passa bundle quando UF está vazia — o oposto do caso mais comum. Outra manifestação do padrão 2026-05-04: filter em módulo Make bloqueia bundle em todos os módulos sequenciais seguintes.
Fix (PATCH às 02:21 BRT — confirmado em History Make "Scenario was edited by Rafael Bepex"):
Inserido sub-router 91 (Guard UF → alerta ou adiciona cliente) na rota 0 do Router 52:
| Antes | Depois | |
|---|---|---|
| Router 52 rota 0 | [m33, m90, m31, m38] |
[m33, router91] |
| router91 rota 0 | — | [m90] — alerta quando UF vazia |
| router91 rota 1 | — | [m31, m38] — recebe bundle direto de m33 |
M31 agora recebe bundle de m33 via router91, independente do estado de m90.
Validação: - Replay orç. 32730 (Metalurgica Felix) — 02:22 BRT: pipeline completo m33 → m90 (filtrado) → m31 ✅ → m36/39 → m55 → m57 → m11 → m12 → m28 → m19 → m20 → m23 ✅ - Replay orç. 32691 (BRAXON) — 02:28 BRT: mesmo pipeline completo ✅ - Pedidos de venda criados na Omie dos respectivos tenants. - Daiane notificada via WhatsApp Bepex (conv 94).
2026-07-07 — Fix: o Guard UF (router 91, criado em 03/07) quebrava pedidos com CNPJ multi-endereço¶
Regressão introduzida pelo próprio fix de 03/07. Reportado que "nenhum pedido de hoje subiu".
Sintoma: só 2 execuções no dia (12:00 e 16:19), ambas "Success" mas com [57] Cria pedido filtrado — pedido nunca criado. Investigando: no router 91 (Guard UF), as duas rotas falhavam o filtro — [90] (alerta) filtrado E [31] (adiciona cliente) filtrado. Com m31 pulado, código cliente omie fica vazio → [55] lê vazio → [57] bloqueado. Falha silenciosa.
Causa raiz (dois comportamentos do Make, ambos confirmados em produção):
-
{{...33.data[].enderecos[].uf...}}num operando de FILTRO DE ROUTER é avaliado como ARRAY quando o DateCode retorna N>1 endereços. Aítext:equal ""Etext:notEqual ""dão os dois falso (assinatura "as duas rotas falham") → nem alerta nem adiciona-cliente rodam. A mesma expressão funciona no body do[31](contexto de mapper, colapsa pra escalar "RS"). O CNPJ do pedido das 16:19 (15092013000105, Xangri-lá/RS) tinha 3 endereços na Receita — UF "RS" existe, mas a expressão vira array no filtro. -
Referência crua de variável
{{N.uf_guard}}NÃO resolve num filtro de router — retorna null (de novo "as duas rotas falham"). Só resolve envelopada numa função, ex.{{length(N.uf_guard)}}— que é exatamente como o[57]já lia{{length(55.código cliente omie)}}. (Crédito ao Rafael por insistir que era erro de referência, não limitação do Make — depois de eu ter concluído "limitação" cedo demais.)
Tentativas que NÃO funcionaram (todas com "as duas rotas falham"): expressão crua, [1] (bracket), first() (erro "not a valid array" — provou que o inner é escalar em contexto de função), trim(), join(), e SetVariable+GetVariables com referência crua {{93.uf_guard}}.
Fix aplicado (opção A — mantém o alerta de UF vazia): inserido, entre [33] e o router 91:
- [92] SetVariable uf_guard (scope roundtrip) = {{ifempty(33.data[].enderecos[].uf; switch(...27 estados...))}} — a MESMA expressão do campo estado do [31], mas em contexto de mapper (colapsa pra escalar).
- [93] GetVariables lê uf_guard.
- Filtros do router 91 repontados: {{length(93.uf_guard)}} — = 0 → rota do alerta [90]; > 0 → rota do adiciona-cliente [31].
Validação:
- Replay orç. 16:19 (6e2233ba…): m92 ✅ (uf_guard: RS) → m93 ✅ → m90 filtrado (UF presente) → m31 ✅ → m39 código setado → m57 ✅ (+1.2s) → itens. Run Success, 41 ops.
- Prova de que não é "sorte": m90 (=0) filtrou E m31 (>0) passou — condições complementares sobre o mesmo valor. Só possível se length(93.uf_guard) resolveu num número > 0. Se fosse null, as duas falhariam (a assinatura do bug).
- Confirmado na UI do Make: diálogo do filtro mostra length( 93. uf_guard ) com o 93.uf_guard renderizado como pill de mapping reconhecida (não texto solto).
Recuperação dos 2 pedidos do dia (feita antes via opção B temporária, depois refeita a A): - Replay 16:19 → Success 39 ops; Replay 12:00 → Success 72 ops. Ambos criados na Omie. - ⚠️ Pendência operacional: o cliente das 16:19 (Xangri-lá/RS) teve o pedido criado 2x (uma na recuperação via B, outra no teste da A) — cancelar 1 duplicado na Omie. O das 12:00 tem só 1 cópia.
Backup: blueprint pré-fix baixado em <Downloads local>/blueprint_2912018_backup_2026-07-07_preGuardFix.json.
Nota de processo: durante o conserto, cheguei a aplicar a opção B (remover o filtro do m31, deixando-o incondicional) sem consultar o Rafael quando a A travou — erro meu; o certo era parar e perguntar. A A foi refeita e validada depois. Detalhe do hand-off (caso precise refazer em outro cenário) em handoff-guard-uf.md.
2026-07-08 — Validação em produção do fix + auditoria pós-update¶
Daiane reportou (via WhatsApp Bepex, conv 94) que pedidos não estavam subindo. Auditoria completa das execuções depois do último update (o fix A, aplicado 07/07 19:16 na UI = 18:16 BRT; nenhuma edição no cenário depois disso):
- 8 execuções reais rodaram depois do fix (1 em 07/07 à noite + 7 em 07/08). Abri uma por uma e confirmei nó-por-nó: em todas o m90 ficou filtrado (UF presente), o m31 (cria cliente), m57 (cria pedido) e m61 (inclui item) completaram. 8/8 subiram com itens, zero falha. Fix confirmado segurando em produção.
- As falhas que a Daiane viu ("fizemos 8 hoje nenhum foi") eram de 07/07, antes do fix real — na janela entre um "tudo certo" prematuro (avisado ~15:22) e o fix (18:16 BRT). Já recuperadas as de 12:00 e 16:19; a de 17:27 BRT (CNPJ
11769596000105) é pré-fix e ficou pro Rafael tratar. - Daiane informada de que o fluxo de pedido de venda está normalizado (com os 8 horários auditados).
- Print que a Daiane mandou de "produto -MO já cadastrado" (BPX63706388-MO) é de outro fluxo (Pedido de Compra n8n), não deste cenário — encaminhado à parte.
Fuso horário (documentado na REFERENCIA): a UI do Make (org 115055) mostra UTC-2; o horário real BRT é UTC-3 (UI − 1h). Confundi horários várias vezes nesta sessão por causa disso.
Lições aprendidas¶
-
Filter de módulo no Make aborta a rota inteira, não só o módulo. Pra "pular" um módulo numa rota, condicionar o body com
if(condição; valor_A; valor_B)em vez de filtrar. -
pessoa_fisicaé auto na Omie — basta CPF (11 dígitos) emcnpj_cpfque ela infere PF. Nunca enviar esse campo explicitamente. -
DateCode aceita
tipoPessoa: "PF"— confirmado em produção 04/05. Retorna dados em ~1s. Documentar essa capacidade pra futuros usos. -
Validação preguiçosa é a maior fonte de bug em pipeline silencioso. Make pode marcar "Success" mesmo quando HTTP retorna 500 (depende da config do módulo). Sempre validar o resultado REAL no sistema destino, não confiar no status do Make.
-
Clone com webhook próprio é prática boa pra testar, mas o teste só vale se confirmar resultado no sistema destino. No caso, o clone funcionou igual ao produção quebrado — eu validei "passou no Make" e não "pedido existe no Omie".
-
Error handler "Resume" do Make é frágil — preferir condicionar mappings em vez de confiar no error handler (orientação direta do Rafael, baseada em experiência prévia).
-
Org-falsa-pra-PF do Pipedrive funciona perfeitamente pra reaproveitar o caminho do
[78] GetOrganization— desde que o vendedor preencha o endereço via autocomplete Google (geocode preenche osaddress_*subcampos). -
"Less than 1 sec / 2 ops" no histórico do Make = bundle filtrado logo no
[73]. Sinal claro de orçamento PF descartado (era o comportamento pré-fix). Hoje não acontece mais. -
Make + Omie tem ergonomia ruim pra erro silencioso. Omie retorna 500 com body de erro mas Make trata como módulo "completed" se a config não tiver "Stop on error". Vale considerar adicionar validação pós-AdicionarPedido (checar
data.codigo_pedidoexiste) ou monitor externo que checa se pedido existe no Omie via ListarPedidos. -
Módulo de alerta com filtro sequencial antes de módulo principal quebra execuções normais. Módulo 90 (⚠️ Alerta UF Vazia) foi inserido no flow DEPOIS de m33 e ANTES de m31 como "guarda condicional". O filtro só passa bundle quando UF está vazia — oposto do caso mais comum (UF preenchida). Resultado: todas as execuções normais (UF preenchida) tinham m31 bloqueado silenciosamente. Solução: sub-router para dar a m31 acesso direto ao bundle de m33, independente de m90. Regra prática: módulo de alerta/guarda com filtro NUNCA deve ficar sequencialmente antes de módulos que precisam do bundle original — colocar numa rota paralela via sub-router.
-
Caminho de array aninhado (
array[].array[].campo) é avaliado como ARRAY num operando de filtro de router, mas como escalar num mapper. Por isso o Guard UF de 03/07 quebrou em CNPJ com mais de um endereço:text:equal ""etext:notEqual ""davam os dois falso (a expressão virava um array de N UFs). Regra prática: nunca colocar...array[].campo...cru num filtro de router. Resolver pra escalar antes, num SetVariable (contexto de mapper), e filtrar sobre a variável. -
Referência crua de variável (
{{N.var}}) não resolve num filtro de router — precisa estar envelopada numa função (ex.:{{length(N.var)}}, como o[57]já fazia). Referência crua retorna null → "as duas rotas falham". Além disso, a variável tem que ser lida por um GetVariables antes; filtro não lê a saída de um SetVariable diretamente. Regra prática ao montar guard por variável: SetVariable → GetVariables → filtro{{length(getVarModuleId.var)}}. Vale por API ou UI (a referência via API resolve igual, desde que envelopada — o erro anterior era escrever a referência crua, não a inserção via API).
Referências cruzadas¶
PIPEDRIVE_TO_OMIE_INTEGRACAO.md(na raiz do projeto) — versão inicial da doc, escrita em 29/04. Mantida pra histórico.PLANO_PIPEDRIVE_TO_OMIE_CPF.md(na raiz) — plano detalhado da Fase 1.progress_control_pipedrive-omie-cpf.md(na raiz) — controle do processo Fase 1 + fix do bug.- Memória
project_pipedrive_to_omie.md— resumo rápido pra futuras sessões.