Comment elles se joignent
cdr_pnl fait un left join submit-final, donc les enregistrements sans résultat pour
l’instant apparaissent comme PENDING — l’exposition en vol reste visible plutôt que d’être exclue
silencieusement.
cdr_submit
La table porteuse. La partie 1 est le seul enregistrement par message de ce qui a été facturé.
Identité et forme
L’argent, des deux côtés
Tout l’argent est un
bigint en dix-millièmes. Divisez par 10 000 pour afficher ; ne stockez
jamais un float.
L’argent vit entièrement sur part_no = 1. Les segments ultérieurs sont des lignes de livraison
sans argent — écrire des montants sur chaque segment multiplierait les deux côtés par le nombre de
segments. Chaque requête d’argent a besoin de WHERE part_no = 1.
Deux devises, et aucune conversion
cost_currency et price_currency sont enregistrées par côté. FireFlo ne convertit jamais entre
elles. Un déploiement qui achète dans une devise et vend dans une autre a une colonne de marge
qui ne peut être sommée sans faire la conversion vous-même.
Les trois colonnes TLV
NULL signifie que rien n’a enregistré la colonne ; {} signifie enregistré et il n’y en avait pas.
tlvs_sent est NULL pour chaque fournisseur non-SMPP.
body, et pourquoi il est habituellement NULL
Enregistré seulement si smsg.cdr.body est excerpt ou full (V1.31.0). NULL sur chaque ligne
sinon, et sur chaque ligne écrite avant que la colonne n’existe.
Cherché avec ILIKE sur un index de trigrammes (V1.32.0), toujours combiné à une plage de dates.
Cet index a besoin de pg_trgm ; si l’utilisateur de migration ne peut créer d’extensions, la
recherche fonctionne encore, plus lentement.
registered_delivery
L’octet SMPP tel que le client l’a envoyé, brut plutôt que décodé — il porte trois requêtes
indépendantes et seules certaines sont honorées.
submit_status et vendor_attempt
Depuis V1.40.0. Une ligne cdr_submit est désormais écrite pour chaque tentative auprès d’un
fournisseur, pas seulement celle qui a finalement réussi ou échoué de manière terminale — un nack
réessayable en écrit une aussi.
Avant cette colonne, une tempête de nouvelles tentatives n’était visible que comme un compte de
soumissions gonflé chez le fournisseur, sans trace de ce qu’il avait réellement répondu sur les
tentatives qui ont échoué — voir Files et nouvelles tentatives
pour le budget de nouvelles tentatives que ces lignes rendent maintenant lisible.
(gateway_msg_id, part_no, retry_count, vendor_attempt) est la clé naturelle depuis V1.40.0, élargie
depuis (gateway_msg_id, part_no, retry_count) — retry_count seul ne change pas à travers les
nouvelles tentatives dans le worker chez un même fournisseur, donc sans vendor_attempt ces lignes
entreraient en collision.
cdr_final et cdr_interim
Résultats et progression, séparés pour la raison ci-dessus. Ils ont aussi des durées de vie
différentes :
dlr_state garde la valeur SMPP brute à côté du résultat grossier, car EXPIRED, REJECTD et
UNDELIV facturent tous comme des échecs mais signifient des choses différentes.
cdr_rejected
Une ligne par refus, avec reason et — depuis V1.27.0 — le code de statut du fournisseur là où le
fournisseur était celui qui refusait.
Une ligne refusée ne porte pas d’argent. price, cost et margin sont NULL car le crédit a
été retourné au moment du refus, ce qui permet aux requêtes de revenu de sommer ces colonnes sans
filtre de résultat.
usage_daily
Une ligne par compte, par produit, par jour. Quotidienne plutôt que mensuelle pour que toute
période soit une SUM sur des jours, pour toujours, sans seconde table dérivée qui pourrait être en
désaccord avec elle.
Les colonnes facturables pour un jour terminé sont finales ; les colonnes de livraison sont
recalculées en relançant le rollup, ce qui la rend idempotente.
Voir aussi
Enregistrements d'appel
À quoi sert chaque table, en prose.
Tables de configuration
L’autre moitié du schéma.