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:- 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.
- Parte dos dados — contas, splits, comissões, métricas — é nossa. Existe independentemente de qual rede liquidou um dado pagamento.
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.
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:
| Campo | Propósito |
|---|---|
| Identificador externo | Identificador atribuído pelo parceiro. Permite voltar ao registro sales correspondente. |
| Status reportado | O que o parceiro reportou mais recentemente (por exemplo OK, DELETED). |
| Status interno | Status livre que a plataforma controla. |
| Última atualização | Quando a plataforma atualizou esta linha pela última vez a partir do parceiro. |
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ção | Lado sales | Lado unified |
|---|---|---|
| Adquirente → plataforma | sales.Transaction | unified.Transaction |
| Adquirente → plataforma | sales.Receivable | unified.Receivable |
| Adquirente → plataforma | sales.Document | unified.Document |
| Adquirente → plataforma | seller.Seller | unified.Account (resolvida via lojista) |
| Plataforma → adquirente | unified.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 registrosales e projeta para a camada unificada.
Os passos-chave:
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.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.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).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.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.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: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.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.Resolução de contas
A ponte entre a entidade lojista específica (no móduloseller) 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
salesnão retornados pela API são deletados. - Registros
unifiedsã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 aDELETEDem vez de removidas fisicamente. A camada unificada nunca apaga registros com base apenas na ausência de uma contraparte na camada de transações.
Escolhendo de qual camada ler
Leitura de dados
Leitura de dados
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.Criação de algo que a plataforma é dona (conta, split, link de convite)
Criação de algo que a plataforma é dona (conta, split, link de convite)
Escreva direto no
unified. A persistência do modelo se encarrega de propagar ao parceiro de processamento quando necessário.Criação de algo no parceiro de processamento (transação, cobrança, upload de documento)
Criação de algo no parceiro de processamento (transação, cobrança, upload de documento)
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.Recuperação após webhook perdido
Recuperação após webhook perdido
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 modelosales que possui uma contraparte unificada implementa esse método. A forma esperada:
- Encerrar cedo se o identificador externo estiver vazio.
- Buscar a linha unificada existente pelo identificador externo; criar uma nova se não houver.
- Definir status reportado, status interno e marca temporal da última atualização.
- Copiar os campos normalizados.
- Resolver as relações (conta receptora, conta do adquirente, transação) através dos auxiliares de resolução por identificador externo.
- 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.