StripeSubscriptionsObjectsIoT. Deux fichiers sont créés, tous deux demandés en mai.
Les huit modifications complètent l’analyse : elles ajoutent ce qui manque, elles ne remplacent
rien.
Côté code, une seule chose change vraiment : le fichier de détails est écrit par le portail à chaque mouvement, là où l’information existe. La tâche planifiée ne fait plus que lire et consolider — elle ne recalcule aucun prorata.
Cinq modifications sur huit sont des demandes de Franck, formulées en mai et reprises ici dans ses termes. Les trois autres sont des propositions issues d’une relecture du modèle de données.
Franck — 21 mai, 13 h 31 « oui il faut créer un fichier historique »→ modification 8,StripeSubscriptionsHistory
Franck — 22 mai, 13 h 58 « pour l'analyse je pense qu'il y aura juste un fichier qui va alimenter les détails avec IDStripeSubscriptions, Descriptions, IDPrix, Quantity, StartDate, EndDate »→ modification 7,StripeInvoicesDetails— nom choisi par Franck le même jour à 14 h 54, structure complétée à 14 h 52 et validée par lui
Franck — 22 mai, 15 h 01 « il faut ajouter un flag dans SSO pour les soft delete, parce que si il y a résiliation, les jauges ne devraient plus être dans SSO après pour ne pas être pris en compte dans la prochaine facturation »→ modification 3,Cancelled
Franck — 22 mai, 15 h 17 « je pense qu'il faut quand même ajouter l'IDPrix dans SSO sans ça on ne sait pas l'historique de changement de plan »→ modification 2,IDStripePrices
Franck — 22 mai, 15 h 25 « notre liaison objet vers SSO est 1,1 il faut mettre à 1,n »→ modification 1, la cardinalité
| N° | Objet | Motif |
|---|---|---|
| 4 | StripeSubscriptions.EndDate nullable |
Absence de date = abonnement en cours sans terme connu. |
| 5 | StripeInvoices.IDStripeSubscriptions nullable |
Une facture de pack SMS n'a pas d'abonnement. |
| 6 | Index composé sur SSO | C'est le parcours exact de la facturation mensuelle. |
IDObjectsIoT sur les lignes qui concernent une jauge, et le lien vers la facture
émise. Un gestionnaire qui conteste obtient le détail sans qu’on refasse le calcul.Dans l'ordre d'exécution. Les modifications portant sur
StripeSubscriptionsObjectsIoT servent les deux modèles de client — gestionnaire
mensuel et client final annuel — ce fichier étant commun aux deux.
ObjectsIoT ↔ StripeSubscriptionsObjectsIoT
à modifier(0,1) côté ObjectsIoT.ObjectsIoT, la
cardinalité passe de (0,1) à (0,n) ; côté
StripeSubscriptionsObjectsIoT elle reste (1,1). La clé
IDObjectsIoT passe d'unique à clé avec doublons.StripeSubscriptionsObjectsIoT.IDStripePrices
à créerStripePrices.StripeSubscriptionsObjectsIoT.Cancelled
à créerStripeSubscriptions.EndDate — accepter la valeur vide
à modifierStripeInvoices.IDStripeSubscriptions — accepter la
valeur vide à modifier0.0.
L'absence d'abonnement se code par une valeur vide, pas par un zéro qui pointerait vers un
abonnement inexistant.IDStripePurchaseSMS, avec IDCustomer en lien direct vers
le client.StripeSubscriptionsObjectsIoT
à créer(IDStripeSubscriptions, Processed).StripeInvoicesDetails
à créerLe détail d'une facture consolidée. Décidé le 22 mai sur proposition de Franck, qui l'a également nommé. Réaffirmé le 10 juin.
IDObjectsIoT ajoutée le 27 août.
IDStripeInvoicesDetails Id. automatique, clé primaire
IDStripeSubscriptions FK → abonnement du gestionnaire
IDStripePrices FK → prix appliqué
IDObjectsIoT FK, valeur vide autorisée → la jauge concernée
Description Texte (libellé interne de la ligne)
Quantity Numérique SIGNÉ
StartDate Date (début de la période couverte)
EndDate Date (fin de la période couverte)
Amount Monétaire SIGNÉ
Processed Booléen, défaut FALSE
IDStripeInvoices FK, valeur vide autorisée → facture émise
IDObjectsIoT est renseignée quand la ligne concerne une
jauge — plan de connectivité, prorata — et vide sinon : abonnement de base,
dépassement consolidé, forfait portant sur tout le parc. Pour le prorata, la facture Stripe ne
porte qu’une seule ligne consolidée, là où ce fichier reçoit une ligne par jauge, avec
son prix, sa période et son montant. C’est ce qui permet de répondre à « ce montant de prorata
correspond à quoi ? » sans reconstituer le calcul.
Le pointeur vise ObjectsIoT et non la ligne
d’abonnement, parce que le forfait device se facture aussi sur les jauges en stock, qui
n’ont aucune ligne dans StripeSubscriptionsObjectsIoT.
IDStripeSubscriptions, IDStripeInvoices et
IDObjectsIoT, toutes avec doublons, plus deux clés composées :
(IDStripeSubscriptions, StartDate) pour le rapprochement différé de la facture,
et (IDStripeSubscriptions, Processed) pour retrouver les cycles non traités.Trois raisons le justifient. On écrit au moment où l’information existe, sans la reconstituer plus tard. La tâche planifiée — la pièce fragile du dispositif — s’en trouve allégée : elle lit et consolide, une requête suffit, et elle ne recalcule jamais un prorata. Enfin, si un cycle n’est pas facturé, les lignes existent déjà en base : le manque devient constatable et rattrapable au lieu de disparaître.
La règle qui va avec : le prorata est calculé une fois, au mouvement. Toute consolidation qui le recalculerait le compterait deux fois.
StripeSubscriptionsHistory
à créerL'historique au niveau abonnement. Demandé par Franck le 21 mai, structure arrêtée le même jour, jamais créé.
StripeSubscriptionsObjectsIoT porte le détail jauge ↔ abonnement ; celui-ci porte
le niveau au-dessus. Les deux sont complémentaires.IDStripeSubscriptionsHistory Id. automatique, clé primaire
IDCustomer FK → client
IDStripeSubscriptions FK historique — peut pointer vers une ligne supprimée
IDStripePrices FK → prix appliqué
StartDate Date
EndDate Date
EndReason Texte libre (trop cher, plus besoin, déménagement…)
Une fois les modifications portées dans l'analyse. Rien de ce qui fonctionne aujourd'hui n'est remis en cause.
C’est là que se concentre le travail : la modification 1 change la logique de clotûre, et c’est aussi ici que le fichier de détails est alimenté.
Cancelled passe à TRUE — et une nouvelle ligne est créée. L'historique se conserve
au lieu de s'écraser.IDStripePrices à chaque création de ligne, avec le
prix effectivement appliqué.StripeInvoicesDetails — Processed à FALSE,
IDStripeInvoices vide, IDObjectsIoT renseignée quand une jauge est
concernée. C’est l’écriture qui remplace le travail de reconstitution à la facturation.IDObjectsIoT garantit à elle seule qu'une jauge n'a
qu'une seule ligne d'abonnement. Après la modification 1, cette garantie n'existe plus au niveau
du fichier. La règle à tenir devient :
une jauge n'a jamais plus d'une ligne non résiliée à un instant donné — unicité sur
(IDObjectsIoT, Cancelled = FALSE). Toute création de ligne doit donc être précédée
de la clôture de la ligne active, dans la même opération. Sans ce contrôle, une jauge peut se
retrouver facturée deux fois sur le même cycle sans qu'aucune erreur ne remonte.
Elle s’allège : les lignes qu’elle devait produire existent déjà en base.
Processed à TRUE. IDStripeInvoices reste vide : la facture naît de
cet envoi et se rapproche plus tard, sur l’abonnement et la période.Aucun des deux ne bloque les huit modifications ci-dessus.
Le passage à la facture consolidée du gestionnaire était en développement le 10 juin, une partie en local. Trois points restent à confirmer avant d'écrire quoi que ce soit :
Une jauge retirée en cours de cycle donne-t-elle lieu à une correction proratisée, ou le cycle entamé est-il dû en entier ? La question a été posée le 22 mai et n'a jamais été tranchée. La seconde règle supprimerait les lignes négatives et le calcul associé, le prorata restant appliqué à l’entrée. Sans effet sur les huit modifications ; à trancher avant d'engager du développement sur ce point.
Identifié, non traité ici.
| Sujet | Nature | Statut |
|---|---|---|
| Supervision de la tâche planifiée — alerte en cas de non-exécution, réconciliation, rattrapage d'un cycle manqué | Développement | Ouvert depuis le 10 juin. Voir encadré ci-dessous. |
| Rejeu de la tâche planifiée — relancer la tâche ne doit pas produire une seconde facture | Développement | Se règle en vérifiant qu'aucune facture n'existe déjà pour ce gestionnaire sur cette
période — les dates sont déjà présentes dans StripeInvoices |
| Écran de consultation du détail d'une facture au portail | Développement | Rendu possible par la modification 7. À planifier séparément : sans cet écran, le détail écrit en base n’est consultable par personne. |
| Transfert d'une sonde d'un client à un autre | Règle métier | Soulevé le 21 mai, jamais traité. La modification 1 le rend techniquement possible. |
Fichier StripePlans | Analyse | Il stocke le prix qu'utilise un abonnement. La modification 2 fait la même chose à un grain plus fin. Laissé en l'état, mais ne rien construire dessus. |
StripeInvoices portant déjà les dates de début et de fin de période, vérifier qu’une
facture n’existe pas déjà pour ce gestionnaire sur cette période suffit à rendre la tâche rejouable
sans risque de double facturation.
Le risque est atténué par l’écriture au mouvement : les lignes d’un cycle manqué sont déjà en base, datées et complètes. Le manque reste invisible pour le client, mais il devient constatable et rattrapable. Il n’est pas supprimé pour autant : les trois garde-fous restent à concevoir.
| N° | Fichier | Objet | Nature |
|---|---|---|---|
| 1 | ObjectsIoT ↔ StripeSubscriptionsObjectsIoT | Cardinalité et unicité | Modification |
| 2 | StripeSubscriptionsObjectsIoT | IDStripePrices | Création |
| 3 | StripeSubscriptionsObjectsIoT | Cancelled | Création |
| 4 | StripeSubscriptions | EndDate — valeur vide autorisée | Modification |
| 5 | StripeInvoices | IDStripeSubscriptions — valeur vide autorisée | Modification |
| 6 | StripeSubscriptionsObjectsIoT | Index (IDStripeSubscriptions, Processed) | Création |
| 7 | StripeInvoicesDetails | Détail de facture (11 rubriques) | Création |
| 8 | StripeSubscriptionsHistory | Historique d’abonnement (7 rubriques) | Création |
Deux rubriques, un index et deux fichiers à créer ; deux propriétés à élargir et une cardinalité à modifier. Aucune contrainte n’est resserrée, donc aucun contrôle de données préalable. L’analyse est ouverte une seule fois.