Pular para conteúdo

Plataforma de Integração

A Plataforma de Integração é como os dados se sincronizam dentro do ecossistema X-Adm — trazer dados do ERP para a nuvem, devolvê-los ao ERP, ou enviar dados a terceiros.

  • Tem como seu ponto central a aplicação tipo Servidor, rodando na nuvem, onde o banco de dados espelha o banco de dados do X-Adm (apenas tabelas e colunas necessárias, não um espelhamento 100% completo). Toda a integração de dados passa por esse servidor, onde cada cliente tem o seu servidor com seu banco de dados.
  • Aliado a isso, cada cliente ou terceiro pode ter seu aplicativo próprio, desenvolvido de acordo com a sua necessidade.

Norma × detalhe

A norma está na constituição §8. Aqui, o contrato operável. O desenho concreto (inventário, roadmap, decisões D0–D13) e o que ainda está em fluxo vivem na arquitetura-alvo, no repo do integrador.

Topologia

Na figura e na taxonomia, Plataforma de Integração nomeia o serviço central por cliente (int.<cliente>).

A figura é a norma em 4 grupos: cliente (servidor X-Adm no cliente: ERP X-Adm + Integrador Cliente, que faz a ponte com a nuvem) — nuvem X-Adm (Wiechert) (Plataforma de Integração, apps específicas, apps compartilhados, banco por cliente) — terceiros (parceiros externos) — usuários (apps consumidor Web e Mobile, que rodam no dispositivo do usuário final, não na nuvem).

SERVIDOR X-ADM CLIENTE TERCEIROS NUVEM X-ADM (WIECHERT) USUÁRIOS ERP X-Adm Integrador Cliente Apps Específicas pied.<cliente>.xadm.biz excel.<cliente>.xadm.biz ecommerce.<cliente>.xadm.biz Plataforma de Integração int.<cliente>.xadm.biz ps.<cliente>.xadm.biz Apps Compartilhados sascar.xadm.biz PostgreSQL Cliente ¹ banco por cliente PIED E-commerce Sascar bi.<cliente>.xadm.biz App Web navegador App Mobile Android / Apple push tempo realwrite-back batch XLSX webhook + pull push pull · MDF-e, odômetro REST REST · baixa MDF-e, odômetro PowerSync PowerSync write-back fluxo de dados integração REST ¹ instância dedicada por cliente

¹ Um banco de dados por cliente.

Nota: apps consumidor (Web e Mobile) bem como o programa Integrador Cliente escrevem de volta à Plataforma de Integração via write-back do PowerSync (campo editável → uploadData → connector → a Plataforma de Integração grava nas tabelas que ela possui) — é a aresta write-back da figura, correndo por fora.

Fonte da figura (Mermaid-base)

A figura acima é um SVG desenhado à mão (assets/topologia-integracao.svg) derivado deste Mermaid, que é a fonte semântica: mudou a topologia, atualize AQUI primeiro e espelhe no SVG.

block-beta
  columns 3
  space
  block:cli
    columns 1
    clit["Servidor X-Adm Cliente"]
    erp["ERP X-Adm"]
    intc["Integrador Cliente"]
  end
  space
  block:ter
    columns 1
    tert["Terceiros"]
    pi["PIED"]
    ec["E-commerce"]
    sa["Sascar"]
  end
  block:nuv:2
    columns 2
    nuvt["Nuvem X-Adm (Wiechert)"]:2
    vert["Apps Específicas<br/>pied.&lt;cliente&gt;.xadm.biz<br/>excel.&lt;cliente&gt;.xadm.biz<br/>ecommerce.&lt;cliente&gt;.xadm.biz"]
    hub["Plataforma de Integração<br/>int.&lt;cliente&gt;.xadm.biz<br/>ps.&lt;cliente&gt;.xadm.biz"]
    vs["Apps Compartilhados<br/>sascar.xadm.biz"]
    pg[("PostgreSQL Cliente ¹")]
  end
  space
  block:usr
    columns 2
    usrt["Usuários"]:2
    appweb["App Web<br/>bi.&lt;cliente&gt;.xadm.biz"]
    appmob["App Mobile<br/>App Android/Apple"]
  end
  space
  erp <-- " " --> intc
  intc -- "push tempo real + write-back" --> hub
  intc -- "batch XLSX" --> vert
  pi -- "webhook + pull" --> vert
  sa -- "pull (MDF-e, odômetro)" --> vs
  vert -- "push" --> ec
  hub <-- "REST" --> vert
  hub <-- "REST (baixa MDF-e, odômetro)" --> vs
  hub <-- " " --> pg
  vert <-- " " --> pg
  vs <-- " " --> pg
  pg -- "PowerSync" --> usr
  pg -- "PowerSync" --> intc
  usr -- "write-back" --> hub

Fluxos principais

Três fluxos contam a plataforma em movimento — cada um com como acompanhar: o mecanismo pelo qual um humano vê se o fluxo rodou ou falhou.

SAÍDA — X-ADM → USUÁRIOS ERP X-Adm Integrador Cliente tempo real batch XLSX Plataforma de Integração excel.<cliente> PostgreSQL PowerSync App Web App Mobile COMO ACOMPANHAR App Web: dado atualizado na tela App Mobile: dado atualizado na tela em tempo real e push de mensagem nos eventos principais App de Integração (excel.<cliente>): tela dedicada que detalha a operação com resultado sucesso/erro Exceções: de software vão automaticamente para bug.xadm.biz (equipe recebe notificação); de operação, a equipe do cliente recebe e-mail
ENTRADA — EXTERNO → X-ADM PIED (parceiro) webhook + pull pied.<cliente> grava PEDIDO Plataforma de Integração (PostgreSQL Cliente) estado-desejado PowerSync Integrador Cliente importa (zimrtmu) ERP X-Adm devolve statusIMPORTADO / ERRO COMO ACOMPANHAR Tela de status em pied.<cliente>.xadm.biz: cada importação com certo / erro Exceções: de software vão automaticamente para bug.xadm.biz (equipe recebe notificação); de operação, a equipe do cliente recebe e-mail — direto da tela
CICLO COMPLETO — X-ADM → NUVEM → PROCESSO → X-ADM (MDF-e) ERP X-Adm MDF-e emitido Integrador Cliente push Plataforma de Integração MDF-e aberto (chave, placa) sascar.xadm.biz polling Sascar (parceiro) chegou ao destino devolve encerrado espelho atualizado→ PowerSync importa no ERP COMO ACOMPANHAR Máquina de estados do MDF-e no espelho (PENDENTE → IMPORTADO / ERRO), visível no App Web sascar.xadm.biz: cadastro e log de polling por cliente — tela multi-tenant Exceções: de software vão automaticamente para bug.xadm.biz (equipe recebe notificação); de operação, a equipe do cliente recebe e-mail ida (fluxo de dados) volta (retorno de status)
Fonte das figuras (Mermaid-base)

Mesma regra da topologia: mudou um fluxo, atualize AQUI primeiro e espelhe no SVG do fluxo (assets/fluxo-saida.svg, assets/fluxo-entrada.svg, assets/fluxo-ciclo-mdfe.svg).

flowchart TB
    subgraph f1["Saída — X-Adm → Usuários"]
        direction LR
        erp1["ERP X-Adm"] --> int1["Integrador Cliente"]
        int1 -- "tempo real" --> plat1["Plataforma de Integração"]
        int1 -- "batch XLSX" --> excel1["excel.&lt;cliente&gt;"]
        plat1 --> pg1[("PostgreSQL")]
        excel1 --> pg1
        pg1 -- "PowerSync" --> web1["App Web"]
        pg1 -- "PowerSync" --> mob1["App Mobile"]
    end
    subgraph f2["Entrada — Externo → X-Adm"]
        direction LR
        pied2["PIED (parceiro)"] -- "webhook + pull" --> app2["pied.&lt;cliente&gt;"]
        app2 -- "grava PEDIDO" --> pg2[("Plataforma de Integração<br/>(PostgreSQL Cliente)<br/>estado-desejado")]
        pg2 -- "PowerSync" --> int2["Integrador Cliente"]
        int2 -- "importa (zimrtmu)" --> erp2["ERP X-Adm"]
        int2 -. "devolve status IMPORTADO/ERRO" .-> pg2
    end
    subgraph f3["Ciclo completo — MDF-e"]
        direction LR
        erp3["ERP X-Adm"] --> int3["Integrador Cliente"]
        int3 -- "push" --> plat3["Plataforma de Integração"]
        plat3 -- "MDF-e aberto (chave, placa)" --> sas3["sascar.xadm.biz"]
        sas3 -- "polling" --> ter3["Sascar (parceiro)"]
        sas3 -. "devolve encerrado" .-> plat3
        plat3 -. "espelho atualizado → PowerSync" .-> int3
        int3 -. "importa no ERP" .-> erp3
    end
    f1 ~~~ f2
    f2 ~~~ f3

Organiza-se por tipo de fluxo, não por cliente

A lógica é que tudo o que é espelho do X-Adm segue o padrão para todos os clientes. O que diverge (aplicações específicas para cliente, integrações com terceiros) fica em aplicativo dedicado. Desta forma mantemos a plataforma central (int.<cliente>) independente, sendo possível evoluir tanto a plataforma como desenvolver aplicações específicas de maneira independente umas das outras.

Taxonomia

Papel O que é Recebe de fora? Dono de Exemplos
Plataforma de Integração A cópia fiel do banco do X-Adm por cliente (réplica do push + dado bruto do ERP) e o connector do PowerSync. Uma por cliente. Só o X-Adm (push/agente) réplica + auditoria int.<cliente> (o integrador, estreitado a este papel)
App específico Serviço específico que recebe de fora, faz o específico do cliente e escreve as suas tabelas. Pode enviar dados para um terceiro ou para o X-Adm. Um por cliente. Sim suas tabelas (bi_*, estado-desejado) excel.<cliente> (XLS), pied.<cliente>
App compartilhado Serviço multi-tenant — 1 instância, N clientes; roteia por cliente na entrada. Nasce quando o parceiro é o mesmo para todos (não faz sentido replicar por cliente). Não escreve no barramento diretamente — conversa com a Plataforma de Integração, que grava no espelho do cliente certo. Detalhe em decisão 0018. Sim (webhook do parceiro + chamadas da Plataforma de Integração de cada cliente) próprio banco de trabalho (cadastro por cliente, credenciais, log de polling) sascar.xadm.biz
App consumidor O que o usuário final usa (Web ou Mobile); lê via PowerSync, escreve só campos editáveis (uploadData → connector da Plataforma de Integração). Não (não é integração) nada / write-back de campo bi.<cliente> (Web), Mobile App do cliente

Os 4 tipos de fluxo

A Plataforma de Integração recebe o tipo 1 (a cópia fiel). Os tipos 2 e 3 entram pelo app específico. O tipo 4 sai de um app específico que recebe da Plataforma de Integração via REST e faz POST no parceiro.

  1. Push X-Adm em tempo real — o X-Adm envia eventos (nota, BL, pedido) por push HTTP direto à Plataforma de Integração, que aplica na réplica. Genérico, igual para todos. (hoje: o integrador.)
  2. Batch de arquivo (XLSX/CSV) — o X-Adm exporta um relatório; o agente entrega o arquivo ao app específico dono (excel.<cliente>), que faz a recepção (dedupe/envelope), parseia e escreve as suas tabelas (bi_*). Divergente por cliente. (hoje: os -xls.)
  3. Pull/webhook de API externa → formato X-Adm (entrada) — o app específico (pied.<cliente>) recebe webhook + faz polling na API na sua porta, transforma para o formato do ERP e grava o estado-desejado (tabelas sem prefixo, com máquina de status por linha). Um cliente Java do lado do ERP importa e devolve o status. (novo: PIED.)
  4. Push para API externa (saída) — um app específico (ecommerce.<cliente>) recebe da Plataforma de Integração via REST (POST /sync/erp no contrato do app), transforma e faz POST numa API de terceiro; é dono da sua tabela de status (idempotência por chave natural). (novo: thoms → WebStorm.)

Combinação ③+④ num app compartilhado. Quando o parceiro é global (mesmo endpoint para todos os clientes), os dois tipos convivem num único app multi-tenant — recebe da Plataforma de Integração (dado que vai para o parceiro) e devolve a ela o retorno do parceiro. A Plataforma de Integração escreve no espelho do cliente certo; o app compartilhado nunca escreve no barramento (para não virar segundo dono). (novo: Sascar — a Plataforma de Integração envia MDF-es abertos com chave/placa; o app compartilhado faz polling na Sascar do cliente com credenciais próprias; quando o motorista chega ao destino, devolve encerrado à Plataforma de Integração, que atualiza o status do MDF-e; o cliente Java lê via PowerSync e importa no ERP. Ver decisão 0018.)

Reator — reservado para uso futuro

Uma versão anterior desta norma listava Reator como 5º papel: serviço que não recebia de fora e consumia o banco via PowerSync para enviar a terceiros. O único caso concreto — thoms → e-commerce — não usa PowerSync (o servidor não o consome; o transporte é POST /sync/erp da Plataforma de Integração para o próprio app), então virou app específico (ecommerce.<cliente>). O papel Reator fica reservado para casos futuros de notificação (email, push, alertas Telegram) — quando aparecer, volta à taxonomia com definição própria.

Fronteiras e owner-writes

O Postgres por cliente é o barramento: cada peça escreve as suas tabelas e lê o resto via PowerSync. Um dono por tabela (quem roda o Flyway e escreve) — o ponto de integração é o banco, não um dispatcher na Plataforma de Integração. O invariante server-side está em Java/Micronaut §Banco.

A convenção de nome de tabela é a propriedade do dado:

Prefixo Significa Sincroniza p/ apps? Dono típico
(sem prefixo) dado do ERP (é, ou vira, dado do X-Adm) Sim Plataforma de Integração (réplica) · app específico (estado-desejado)
<dominio>_ derivado do processamento, consumido por app Sim app específico (bi_*)
<app>_ controle interno (staging, tabela de status por chave natural) Não app específico (xls_*, thoms_envio)

Um app específico que envia para fora (tipo ④) nunca marca estado numa coluna da tabela-espelho (isso daria dois donos à réplica) — tem a sua tabela de status (<app>_envio), separada.

Dentro da tabela-espelho, a fidelidade é por coluna. O prefixo diz de quem é a tabela; dentro de uma tabela-espelho (sem prefixo), o que rege cada coluna é: o espelho modela a entidade do X-Adm, não a do parceiro. A identidade (chave de negócio, critério de join) vive sempre em coluna nativa do X-Adm, conferida contra a spec de entidades do ERP. Um campo que só existe no vocabulário da fonte externa (ex. codigo_alt, x_ped de um parceiro) entra prefixado pela origem e é só rastreabilidade:

Coluna Origem Papel Vira identidade/join?
(sem prefixo, nativa) modelo do X-Adm identidade, join, negócio Sim
<origem>_<campo> sistema externo (ex. pied_x_ped) rastreabilidade / transporte Não

A coluna <origem>_ sincroniza como o resto da tabela (a tabela é sem prefixo), mas o consumidor a lê para auditar, nunca para casar registros. Deixar a chave do parceiro virar identidade de 1ª classe acopla o espelho ao vocabulário de um terceiro — o oposto de "cópia fiel do X-Adm" (decisão 0009).

Transporte X-Adm↔nuvem (padrão único por direção)

Muda o processamento e o destino, nunca o transporte:

  • Saída — tempo real: push HTTP direto à Plataforma de Integração (o /api/v1/xadm de hoje). Contrato legado: responde sempre 200, erro no corpo.
  • Saída — arquivo/lote: o X-Adm grava numa outbox local; um agente .jar genérico observa a pasta (~1 min) e envia à nuvem, roteando por tipo (config, não código): dado bruto do ERP → a Plataforma de Integração; relatório → o app específico dono. O X-Adm fica desacoplado do destino.
  • Entrada no ERP: a nuvem grava tabelas-espelho (sem prefixo, com status PENDENTE→PROCESSANDO→IMPORTADO→ERRO) no banco do cliente; um cliente Java do lado do ERP conecta via PowerSync, lê o PENDENTE, importa chamando o zimrtmu.exe (runtime do ZIM) e escreve o status de volta. O mesmo contrato para qualquer fonte de entrada.

O transporte é PowerSync bidirecional (connector na Plataforma de Integração) para os apps consumidor (Web e Mobile) e para o cliente Java do lado do ERP; entre a Plataforma de Integração e apps específicos que enviam para fora, o transporte é REST (o servidor Java não consome PowerSync — ver 0018 e §Os 4 tipos, tipo ④). A tech (connector, write-back, auth, config do PowerSync) está em PowerSync.

Na direção inversa — quando um app chama outro via REST (o poke "algo mudou, vá puxar"; o integrador ao app é o caso comum) — a rota do lado do chamado segue /api/<origem>/<recurso>, com <origem> = o app chamador (/api/integrador/produto): auth uniforme (ROLE_API no /api/**) e caminho previsível. E a env de auth/URL de cada aresta se nomeia pelo destino<APP>_URL + <APP>_API_TOKEN, um token por app chamado, mesmo valor no validador e em todos os callers — para o mapa de segredo não colidir num app que é chamador e chamado ao mesmo tempo (Segurança §Segredos · Java/Micronaut §Específico).

Arestas concretas (call-graph)

O diagrama e os fluxos acima nomeiam as famílias de aresta; esta tabela é o call-graph concreto server-server que a auditoria levantou — caller → callee, transporte, endpoint e auth por linha. Não é a topologia (essa é a figura); é o inventário do que fala com o quê hoje.

Caller Callee Transporte Endpoint (no callee) Auth
ERP X-Adm (push) Plataforma de Integração (int.<cliente>) HTTP push PUT/DELETE /api/v1/xadm Bearer, 1 token por instância
Plataforma de Integração app compartilhado (sascar.xadm.biz) REST POST /api/integrador/mdfe/watch Bearer M2M (<CALLEE>_API_TOKEN)
app compartilhado (Sascar) Plataforma de Integração REST POST /api/sascar/encerramento Bearer M2M, token-tenant (0018)
App novo (bootstrap) Central (broker de setup) REST POST /api/setup/provision Bearer, token de serviço do broker
Integrador Cliente pAbast (parceiro) dXp (dXpEnvio/dXpRetorno) — (protocolo do parceiro) credencial do parceiro

Notas:

  • /api/<origem>/<recurso> — o poke leva o chamador no prefixo: /api/integrador/… é rota no app compartilhado, chamada pela Plataforma de Integração; /api/sascar/… é rota na Plataforma, chamada pelo app compartilhado (§Transporte, direção inversa · Java/Micronaut §Específico).
  • Status por caso — a aresta de push do ERP responde sempre 200 (erro no corpo, contrato legado que a fila exige); par app↔app novo sem PowerSync usa status HTTP real (decisão 0020).
  • O detalhe exato de cada endpoint (schema do corpo, contrato) vive no repo dono do callee (§1.9) — aqui fica o mapa, não o contrato. A dXp/pAbast é da Fase 5 (integrador-client, amarrado ao ERP), fora deste escopo.

Concreto, roadmap e decisões

O inventário de projetos, os diagramas de ponta a ponta, o roadmap de migração e as decisões D0–D13 vivem na arquitetura-alvo do integrador — é o desenho volátil, que evolui no repo da integração sem tocar a constituição.