Facturation

Clients, factures avec ventilation TPS et TVQ, paiement Stripe et Interac, récurrences, rappels et intérêts de retard.

@lrvo/module-billing ajoute une section « Facturation » à l'admin : un fichier clients, un catalogue d'articles, des factures avec ventilation TPS et TVQ, et une page publique où le client règle sa facture par carte ou par virement Interac.

Le module est autonome. Il porte ses propres clients plutôt que de dépendre d'un module externe, et se relie facultativement aux comptes du site par la colonne user_id.

La liste des factures, ses totaux en tête et ses onglets de statut

Une facture ouverte dont l'échéance est passée affiche « En retard » dans la colonne « Statut », et le nombre de jours de retard sous l'échéance, alors que son statut stocké reste sent ou partial : c'est une déduction, pas un état stocké, et Facturation explique pourquoi. Le décompte sous l'échéance ne paraît que tant qu'un solde reste dû. Une facture payée, annulée ou en brouillon n'en porte aucun. Le brouillon en tête de liste n'a ni numéro ni lien public, il ne les reçoit qu'à l'émission.

Pages de cette section

PageContenu
InstallationInstaller le module, créer les tables, déclarer le webhook Stripe.
ConfigurationVariables d'environnement, permissions, entrée d'admin.
Cycle de vie d'une factureBrouillon, émission, encaissement, annulation.
TaxesProfils, base de calcul, arrondi, numéros d'inscription.
PaiementsStripe, Interac, saisie manuelle et remboursements.
Récurrences et rappelsGénération automatique, échelle de rappels, intérêts.
CourrielsLes six messages, leur contenu et leur non-répétition.
Modèle de donnéesLes douze tables lrvo_billing_*.
APIRoutes HTTP et fonctions serveur importables.

Ce que le module apporte

ÉlémentDétail
TablesDouze, toutes préfixées lrvo_billing_.
Entrée d'adminSection « Facturation », icône InvoiceIcon, ordre 150, six items.
Tableau de bordUn panneau « Facturation » sur /admin : revenus de la semaine, du mois et de l'année, à encaisser, en retard, et douze mois de revenus en graphique.
Permissionsbilling.view et billing.manage.
Routes API44 routes d'admin, 4 routes publiques.
Rendu publicUne page de paiement à /lrvo/billing/<token> et deux visionneuses de documents, enregistrées par la sous-entrée ./public-page.
Tâches planifiéesTrois : intérêts, récurrences, rappels.
DocumentsFacture et reçu en PDF, générés à la demande.
CourrielsSix, du courriel d'émission à l'avis de remboursement. Voir Courriels.

Deux principes qui expliquent le reste

Le solde est calculé à un seul endroit. computeBalance dans money.js produit le montant dû, et c'est ce nombre qui sert à la session Stripe, au PDF, à la page publique, aux courriels, à la colonne Solde et au principal des intérêts. Aucune seconde formule ne peut diverger.

Le retard n'est pas un statut. Une facture est draft, sent, partial, paid ou cancelled. Le retard se déduit de la date d'échéance et du solde, à la lecture. Une facture en retard reste donc sent ou partial, et ne peut pas disparaître de la requête qui alimente les avis de retard.

Montants et unités

Tout est stocké en entiers, jamais en flottants ni en décimaux.

GrandeurUnitéExemple
MontantCent11498 vaut 114,98 $
QuantitéMillième1500 vaut 1,5
Taux de taxePartie par million99750 vaut 9,975 %

Une colonne DECIMAL revient de pg sous forme de chaîne, ce qui oblige à un parseFloat à chaque lecture et ouvre autant d'occasions d'erreur d'arrondi. Les cents correspondent en prime exactement à ce qu'attend l'API Stripe.

Notes

  • La page publique est protégée par un jeton de 64 caractères hexadécimaux, et rien d'autre. Toute personne qui détient le lien voit la facture et peut la payer. Le jeton n'expire pas et ne se révoque pas.
  • Les PDF publics s'affichent dans une visionneuse plutôt que de se télécharger. Le routeur du core sert par défaut en pièce jointe tout ce qui n'est pas une image ; les deux routes de document demandent explicitement l'affichage en ligne, ce qu'elles peuvent faire parce qu'elles rendent le document elles-mêmes au lieu de le relire depuis le stockage.
  • Le webhook Stripe est servi par le core, sur /lrvo/api/payments/stripe/webhook. Le module s'y abonne : le projet hôte n'a aucune route à créer, seulement l'endpoint à déclarer chez Stripe. Voir Installation.
  • Le champ version du manifeste vaut 1.0.0 et ne suit pas la version du paquet. Se fier à package.json.

Sur cette page