Como se juntam
cdr_pnl faz left join de submit e final, então registros sem desfecho ainda aparecem
como PENDING. Exposição em voo continua visível em vez de ser excluída em silêncio.
cdr_submit
A tabela portadora. A parte 1 é o único registro por mensagem do que foi cobrado.
Identidade e formato
O dinheiro, os dois lados
Todo dinheiro é
bigint de décimos-milésimos. Divida por 10 000 para exibir; nunca guarde um
float.
O dinheiro vive inteiramente em part_no = 1. Segmentos posteriores são linhas de entrega sem
dinheiro. Escrever valores em cada segmento multiplicaria os dois lados pela contagem de segmentos.
Toda query de dinheiro precisa de WHERE part_no = 1.
Duas moedas, e sem conversão
cost_currency e price_currency são registradas por lado. FireFlo nunca converte entre elas.
Uma implantação comprando em uma moeda e vendendo em outra tem uma coluna de margin que não pode ser
somada sem fazer a conversão você mesmo.
As três colunas de TLV
NULL significa nada registrou a coluna; {} significa registrado e não havia nenhum. tlvs_sent
é NULL para todo fornecedor não-SMPP.
body, e por que geralmente é NULL
Registrado só se smsg.cdr.body é excerpt ou full (V1.31.0). NULL em toda linha caso
contrário, e em toda linha escrita antes de a coluna existir.
Pesquisado com ILIKE sobre um índice trigram (V1.32.0), sempre combinado com uma faixa de data.
Esse índice precisa de pg_trgm; se o usuário de migração não pode criar extensões, a busca ainda
funciona, mais devagar.
registered_delivery
O octeto SMPP como o cliente enviou, cru em vez de decodificado. Ele carrega três pedidos
independentes e só alguns são atendidos.
submit_status e vendor_attempt
Desde V1.40.0. Uma linha cdr_submit agora é escrita para toda tentativa contra um fornecedor,
não somente aquela que finalmente teve sucesso ou falhou terminalmente — um nack retentável escreve
uma também.
Antes desta coluna, uma tempestade de retentativas era visível somente como uma contagem de submits
inflada no fornecedor, sem registro do que ele efetivamente disse nas tentativas que falharam — veja
Filas e retentativas para o orçamento de retentativas que
essas linhas agora tornam legível.
(gateway_msg_id, part_no, retry_count, vendor_attempt) é a chave natural a partir de V1.40.0,
alargada de (gateway_msg_id, part_no, retry_count) — retry_count sozinho não muda entre
retentativas dentro do worker em um fornecedor, então sem vendor_attempt essas linhas colidiriam.
cdr_final e cdr_interim
Desfechos e progresso, separados pela razão acima. Também têm vidas diferentes:
dlr_state guarda o valor SMPP cru ao lado do desfecho grosseiro, porque EXPIRED, REJECTD e
UNDELIV todos billam como falha mas significam coisas diferentes.
cdr_rejected
Uma linha por recusa, com reason e, desde V1.27.0, o código de status do fornecedor quando o
fornecedor foi o que recusou.
Uma linha recusada não carrega dinheiro. price, cost e margin são NULL porque o crédito
foi devolvido no momento da recusa, o que permite que queries de receita somem essas colunas sem um
filtro de desfecho.
usage_daily
Uma linha por conta, por produto, por dia. Diário em vez de mensal para que qualquer período seja
um SUM sobre dias, para sempre, sem uma segunda tabela derivada que discorde.
Colunas billable de um dia terminado são finais; colunas de entrega são restatadas rodando o rollup
de novo, e é por isso que é idempotente.
Relacionados
Call records
Para o que cada tabela serve, em prosa.
Tabelas de configuração
A outra metade do schema.