Elas fazem join em
(gateway_msg_id, part_no). A view cdr_pnl faz left-join entre submit e final,
portanto registros ainda sem desfecho aparecem como PENDING. A exposição em trânsito permanece
visível em vez de ser silenciosamente excluída dos seus números.
Por que recibos de progresso vivem na sua própria tabela
Um vendor pode enviar vários recibos para uma mensagem:ACCEPTD ao aceitá-la, BUFFRED enquanto
retenta, e depois DELIVRD ou uma falha. Somente o último é um desfecho.
Todo leitor pega a primeira linha cdr_final de uma mensagem: a lista de mensagens, o dashboard
do portal, as queries de receita e a view cdr_pnl todos fazem isso. Portanto, gravar recibos de
progresso em cdr_final faria um ACCEPTD sobrepujar o DELIVRD que o seguiu, em toda lista, todo
gráfico e no P&L.
O expiry sweep depende da mesma coisa: ele encontra mensagens não resolvidas por meio de anti-join em
cdr_final, portanto um recibo de progresso ali faria uma mensagem aberta parecer fechada e ela nunca
seria revisitada.
As duas tabelas também têm tempos de vida diferentes. cdr_final é histórico de billing e vive
enquanto o CDR. cdr_interim é histórico de qualidade — quão rápido um vendor reporta e se
reporta ou não — o que é uma pergunta sobre tráfego recente, portanto ela é podada em sua própria
janela mais curta (smsg.cdr.interim.retention.days, default 30). Perdê-la custa um relatório, não uma fatura.
Ambos os lados da negociação
Rate, units e total são registrados separadamente por lado, porque os dois podem legitimamente cobrar contagens de unidades diferentes para uma mensagem — um vendor cobra por segmento onde você pode cobrar por mensagem.
Para uma mensagem concatenada o dinheiro vive inteiramente na parte 1, cujo custo já cobre todos
os segmentos. Segmentos posteriores são linhas de entrega sem dinheiro. Gravar valores em todos os
segmentos multiplicaria os dois lados pela contagem de segmentos.
Uma mensagem recusada não carrega dinheiro
Qualquer coisa que chegou a um vendor tem uma linha emcdr_submit, aceita ou não. Uma mensagem que
o vendor recusou é registrada por completo — identidade, timing, vendor, endereços — mais uma linha
em cdr_final e uma em cdr_rejected carregando o status code do vendor.
Mas price, cost e margin são null, porque o crédito do cliente foi devolvido no momento da
recusa.
As três colunas de TLV
Três pontos em um mesmo pipeline. Toda pergunta útil é uma comparação entre dois deles.NULL significa que nada registrou a coluna; {} significa que foi registrado e não havia nenhum.
tlvs_sent é NULL para todo vendor não-SMPP.
Lendo uma tempestade de retentativas
Toda tentativa em um vendor agora deixa sua própria linhacdr_submit — não somente aquela que
finalmente teve sucesso ou falhou terminalmente. vendor_attempt as numera, submit_status carrega o
que o vendor efetivamente disse em cada uma, e NULL ali significa “não registrado”, não “aceito”.
Veja Tabelas de call record para o formato exato.
O corpo da mensagem
Registrado somente se você ativar.
Um valor não reconhecido é tratado como
off. A falha que importa é armazenar conteúdo que ninguém
pediu para armazenar, portanto um erro de digitação não deve ligar a gravação.
Desfechos
dlr_state mantém o valor bruto do SMPP ao lado do desfecho grosseiro, porque EXPIRED, REJECTD
e UNDELIV todos são faturados como falhas mas vale a pena distingui-los.
O expiry sweep fecha qualquer coisa passada de seu prazo como EXPIRED, deixando o billing
decidir quanto vale um desfecho desconhecido. O prazo é limitado a três dias: passada a janela de
correlação, um recibo já não pode ser casado mesmo se chegar, portanto esperar mais não muda a resposta.
Se uma mensagem não aparece em lista nenhuma
O writer normalmente está apontado para um banco de dados diferente do painel. Verifiquesmsg.cdr.sink e o FIREFLO_DB_URL do gateway contra o METRICS_DATABASE_URL do painel antes de
olhar em qualquer outro lugar.
Relacionado
Uso e retenção
O que sobrevive quando os call records são purgados.
Como o pricing funciona
Onde cada lado da negociação é liquidado.