A plataforma oferece, por meio da camada unificada, uma visão única de contas, transações, recebíveis e depósitos, independentemente de qual rede de adquirência ou parceiro de processamento esteja por trás da operação. Os dados de pagamento ficam armazenados em dois lugares: uma vez no módulo sales como verdade específica do adquirente, e uma vez no módulo unified como espelho agnóstico do adquirente. Toda visão do painel, todo relatório e todo consumidor externo da API leem da camada unificada. Esta página explica por que essa divisão existe, o que cada camada guarda e como os dados fluem entre elas.

Por que uma camada unificada

A plataforma integra diferentes parceiros de processamento. Cada um deles tem formatos próprios, ciclos de vida distintos, identificadores e particularidades. Duas consequências se seguem:
  1. Se cada interface e relatório consultasse tabelas específicas de cada parceiro, precisaria conhecer cada uma delas. Adicionar um novo parceiro exigiria reescrever cada caminho de leitura.
  2. Parte dos dados — contas, splits, comissões, métricas — é nossa. Existe independentemente de qual rede liquidou um dado pagamento.
A camada unificada resolve as duas coisas: é a projeção agnóstica de tudo aquilo com que o negócio se importa. Leituras passam por ela. Escritas ou começam nela (quando o dado é nosso) ou são projetadas a partir do módulo sales (quando o dado originou-se na adquirência).
Regra prática: o módulo sales conversa com os parceiros de processamento; o módulo unified conversa com o seu painel e com seus consumidores de API.

As duas metades do modelo de dados

Modelos sales (camada de adquirência)

O módulo sales mantém a verdade específica do adquirente. Os registros espelham o que existe no parceiro de processamento usando um identificador externo como chave única. Exemplos:
  • sales.Transaction — uma linha por transação no parceiro, com o conjunto completo de campos retornados (taxas, pré-autorização, valor original etc.).
  • sales.Receivable, sales.SplitRule, sales.Document, sales.PaymentMethod, sales.PaymentAuthorization, modelos de transferência e de ponto de venda.
Cada modelo sales possui um método de atualização que cria ou atualiza sua contraparte unificada.

Modelos unified (camada agnóstica)

Cada modelo unificado que se origina de um parceiro de processamento estende uma base abstrata comum que adiciona quatro campos:
CampoPropósito
Identificador externoIdentificador atribuído pelo parceiro. Permite voltar ao registro sales correspondente.
Status reportadoO que o parceiro reportou mais recentemente (por exemplo OK, DELETED).
Status internoStatus livre que a plataforma controla.
Última atualizaçãoQuando a plataforma atualizou esta linha pela última vez a partir do parceiro.
Sobre essa base estão construídos os modelos unificados: Account, Transaction, Receivable, AccountDeposit, AccountDepositTransactions, AccountDepositDestination, Document, PointOfSale, TokenizedCard. Somam-se a eles modelos que são puramente nossos (sem contraparte na adquirência): Split, InvitationLink, Person, Company, BankAccount e todas as tabelas de métricas.

O mapeamento na prática

DireçãoLado salesLado unified
Adquirente → plataformasales.Transactionunified.Transaction
Adquirente → plataformasales.Receivableunified.Receivable
Adquirente → plataformasales.Documentunified.Document
Adquirente → plataformaseller.Sellerunified.Account (resolvida via lojista)
Plataforma → adquirenteunified.Document (upload)sales.Document é então criado/sincronizado quando o upload conclui

Fluxo de dados: adquirente → sales → unified

Esse é o caminho mais comum. Um webhook chega, a plataforma busca o estado autoritativo no parceiro, persiste o registro sales e projeta para a camada unificada. Os passos-chave:
1

Webhook persistido, ouvinte invocado

O receptor de webhook parseia o corpo e o entrega ao serviço de webhooks. O payload é salvo como ReceivedWebhookCall e despachado para todos os ouvintes registrados. Hoje o ouvinte relevante é o despachante da camada de transações.
2

O ouvinte enfileira um job da camada sales

O despachante lê event['type'] e chama o auxiliar de enfileiramento correspondente. Para eventos de transação é o equivalente a fetch_transaction com execução imediata. Para recebíveis é fetch_receivables. Para transferências, update_transfer. Para eventos de lojista, documento e conta bancária, equivalentes.
3

O job sales busca no parceiro

O job usa o cliente HTTP do parceiro para buscar o estado canônico. Cria ou atualiza a sales.Transaction indexada pelo identificador externo. Registros retornados pelo parceiro sobrescrevem campos locais; registros não retornados durante uma sincronização completa são tipicamente removidos da tabela sales (veja Limpeza de dados obsoletos).
4

A persistência do modelo sales dispara a atualização unificada

sales.Transaction.save() verifica os indicadores de controle (skip_unified, sync_with_zoop). Se nenhum estiver ativo, dispara update_unified_transaction_job e fetch_receivables. Portanto a persistência é o que faz o trabalho se ramificar.
5

O job unificado atualiza a contraparte

O job unificado carrega a transação sales e invoca o método de atualização. Esse método procura a unified.Transaction existente pelo identificador externo ou cria uma nova, e então copia os campos normalizados (valor, status, tipo de pagamento, bandeira do cartão etc.). Também resolve receiver_account e acquirer_account através da conta unificada do lojista.
6

Métricas e webhooks de saída são atualizados

Em uma mudança de status, a atualização recalcula as tabelas de métrica relevantes (SalesByDate, ProductByDate etc.) com expressões atômicas para evitar condições de corrida. Em seguida, a rotina de despacho envia a transação serializada via POST para cada webhook de saída registrado pelo lojista.

Fluxo de dados: plataforma → adquirente (uploads)

Quando o dado nasce na plataforma (upload de documento, criação de conta, recebível manual), a ordem se inverte:
1

Escreve primeiro no unificado

O endpoint cria o registro unificado (por exemplo, um unified.Document) com o arquivo armazenado em nuvem e o status reportado como UNDEFINED.
2

Enfileira um job da camada sales

Um auxiliar de enfileiramento dispara um job (por exemplo upload_document). O job baixa o arquivo do armazenamento em nuvem e o envia ao parceiro de processamento.
3

Registro sales é criado em caso de sucesso

O job cria o sales.Document indexado pelo novo identificador externo retornado, invoca a atualização da contraparte unificada, e a linha unificada passa a carregar o identificador externo e um status OK.
A criação de conta segue o mesmo formato: a persistência da conta unificada enfileira o job de registro junto ao parceiro quando o registro automático está habilitado, e o identificador externo retornado é gravado de volta no registro local.

Resolução de contas

A ponte entre a entidade lojista específica (no módulo seller) e a unified.Account agnóstica é o identificador externo do lojista. Modelos sales usam essa resolução sempre que precisam definir a conta receptora ou a conta do adquirente em uma contraparte unificada. O caminho reverso permite recuperar a entidade do lojista a partir do identificador da conta unificada.

Limpeza de dados obsoletos

Quando a plataforma sincroniza a partir do parceiro de processamento, ele é tratado como verdade absoluta:
  • Registros sales não retornados pela API são deletados.
  • Registros unified são tratados de forma mais conservadora: apenas linhas que de fato possuem um identificador externo são elegíveis para serem marcadas como obsoletas, e são sinalizadas com status reportado igual a DELETED em vez de removidas fisicamente. A camada unificada nunca apaga registros com base apenas na ausência de uma contraparte na camada de transações.
Isso protege dados unificados que são genuinamente nossos (uma configuração de split, um link de convite) de serem apagados por uma particularidade do parceiro.

Escolhendo de qual camada ler

Sempre do unified. Os endpoints de leitura unificados estão aninhados sob /sellers/{sellers_pk}/ e são o que qualquer consumidor da API deve utilizar.
O endpoint chama um método em um modelo unificado (por exemplo Account.create_transaction(...)) que delega para a camada sales. O lado sales conversa com o parceiro e depois projeta de volta para o unified.
Reexecute o job de busca da camada sales correspondente (fetch_transaction, fetch_receivables etc.). O caminho de sincronização completa é o mesmo do caminho de webhook — apenas disparado manualmente.

O contrato de atualização da contraparte unificada

Todo modelo sales que possui uma contraparte unificada implementa esse método. A forma esperada:
  1. Encerrar cedo se o identificador externo estiver vazio.
  2. Buscar a linha unificada existente pelo identificador externo; criar uma nova se não houver.
  3. Definir status reportado, status interno e marca temporal da última atualização.
  4. Copiar os campos normalizados.
  5. Resolver as relações (conta receptora, conta do adquirente, transação) através dos auxiliares de resolução por identificador externo.
  6. Persistir o registro. Se o modelo unificado possui dados derivados próprios (por exemplo, atualização de status de recebível que dispara métricas), deixe essas rotinas seguirem seu fluxo.

Guias relacionados

Arquitetura

Como a camada unificada se encaixa na arquitetura em quatro camadas e no sistema de jobs.

Webhooks e jobs

Tipos de eventos, encadeamento de jobs e estratégia de replay.

Fluxo de transação

Um passo a passo concreto de um pagamento, da criação à liquidação do recebível.

API de contas unificadas

Os endpoints sustentados pela camada unificada.