API

Routes HTTP du module de facturation et fonctions serveur importables depuis le projet hôte.

Fonctions serveur

Un composant serveur, un template ou une page du projet hôte lit la base directement, jamais par un appel HTTP à ses propres routes.

import {
  getInvoiceById,
  getInvoiceByToken,
  listInvoices,
  getInvoiceStats,
  getClientById,
  getClientByUserId,
  listClients,
  listTransactions,
  listInvoiceTransactions,
  computeBalance,
  computeInvoiceTotals,
  formatCents,
  getBillingConfig,
  isBillingEnabled,
} from '@lrvo/module-billing/server';

getClientByUserId(userId) est le point d'accroche d'un portail client : elle résout le compte connecté vers sa fiche de facturation, dont l'identifiant sert ensuite à filtrer listInvoices.

Routes HTTP

Toutes sous /lrvo/api/billing/. Les routes d'admin demandent une session administrateur, plus la permission indiquée. Le routeur applique la limite de débit, la protection CSRF, l'authentification et la permission avant d'atteindre le module.

Configuration

MéthodeCheminPermission
GET/admin/configbilling.view

Renvoie ce dont l'admin a besoin pour dessiner ses formulaires : taxesEnabled, defaultTaxProfile, gstRatePpm, qstRatePpm et currency. C'est une lecture de l'environnement, pas un réglage : il n'y a pas d'écriture correspondante.

Clients

MéthodeCheminPermission
GET/admin/clientsbilling.view
POST/admin/clientsbilling.manage
GET/admin/clients/:idbilling.view
PUT/admin/clients/:idbilling.manage
DELETE/admin/clients/:idbilling.manage
POST/admin/clients/:id/interacbilling.manage

GET /admin/clients?options=true renvoie la liste compacte des clients actifs, pour un sélecteur.

Catégories et articles

MéthodeCheminPermission
GET / POST/admin/categoriesbilling.view / billing.manage
GET / PUT / DELETE/admin/categories/:idbilling.view / billing.manage
GET / POST/admin/itemsbilling.view / billing.manage
GET / PUT / DELETE/admin/items/:idbilling.view / billing.manage

?options=true fonctionne aussi sur ces deux ressources. Sur les catégories, elle renvoie l'arbre aplati avec une profondeur, pour une liste indentée.

La suppression d'un article référencé par une facture le désactive au lieu de le supprimer, et la réponse le dit.

Factures

MéthodeCheminPermission
GET/admin/invoicesbilling.view
POST/admin/invoicesbilling.manage
GET/admin/invoices/statsbilling.view
GET/admin/invoices/:idbilling.view
PUT/admin/invoices/:idbilling.manage
DELETE/admin/invoices/:idbilling.manage
POST/admin/invoices/:id/issuebilling.manage
POST/admin/invoices/:id/resendbilling.manage
POST/admin/invoices/:id/cancelbilling.manage
POST/admin/invoices/:id/duplicatebilling.manage
GET/admin/invoices/:id/pdfbilling.view
GET / POST/admin/invoices/:id/transactionsbilling.view / billing.manage

Filtres de la liste : status, clientId, overdue=true, from, to, search, page, limit, sortBy, sortOrder.

sortBy passe par une liste blanche : une valeur inconnue retombe sur le tri par défaut, elle n'atteint jamais la requête.

overdue=true n'est pas un statut mais une clause de recherche : échéance passée et solde positif.

Transactions

MéthodeCheminPermission
GET/admin/transactionsbilling.view
GET/admin/transactions/:idbilling.view
PUT/admin/transactions/:idbilling.manage
DELETE/admin/transactions/:idbilling.manage
POST/admin/transactions/:id/refundbilling.manage
GET/admin/transactions/:id/receiptbilling.view

PUT et DELETE répondent 409 sur une transaction Stripe : le registre doit refléter ce que le processeur a fait, et l'annulation d'un encaissement Stripe passe par un remboursement.

Récurrences

MéthodeCheminPermission
GET / POST/admin/recurrencesbilling.view / billing.manage
GET / PUT / DELETE/admin/recurrences/:idbilling.view / billing.manage
POST/admin/recurrences/:id/runbilling.manage

Tâches planifiées

MéthodeCheminPermission
GET/admin/jobsbilling.view
POST/admin/jobs/:name/runbilling.manage

POST .../run répond 409 quand la tâche est déjà en cours : le déclenchement manuel passe par le même verrou que le déclenchement planifié.

Routes publiques

MéthodeCheminRôle
GET/public/:tokenCharge publique de la facture.
POST/public/:token/checkoutOuvre une session de paiement pour le solde.
GET/public/:token/pdfPDF de la facture.
GET/public/:token/receiptReçu, une fois la facture soldée.

Le jeton est obligatoire sur chacune. Son format, 64 caractères hexadécimaux, est vérifié avant toute requête en base, et la recherche exclut les brouillons. Aucun chemin ne résout une facture par son identifiant numérique.

La charge publique est réduite : ni identifiant numérique, ni notes internes, ni adresse du client.

POST /public/:token/checkout ne prend aucun corps. La facture et le montant sont dérivés du jeton côté serveur, donc il n'y a rien à falsifier.

Les deux routes de document répondent en Content-Disposition: inline : le navigateur affiche le PDF au lieu de le télécharger, ce qui permet aux pages /lrvo/billing/<jeton>/pdf et /recu de le présenter dans une visionneuse. Le document est rendu à chaque requête, jamais relu depuis le stockage. /public/:token/receipt répond 409 tant que le solde n'est pas nul.

Codes d'erreur

SituationCode
Identifiant ou corps invalide400
Permission manquante403
Facture, client ou article introuvable404
Facture déjà émise, lignes figées, transaction Stripe, tâche en cours409

Notes

  • Les PDF sont servis en pièce jointe. Le routeur du core impose Content-Disposition: attachment pour tout ce qui n'est pas une image, et pose X-Frame-Options: DENY : un PDF ne peut donc pas s'afficher dans un cadre.
  • Le webhook Stripe n'est pas dans ce tableau : il appartient au core, sur /lrvo/api/payments/stripe/webhook, et le module s'y abonne. Voir Installation.
  • Les pages d'admin appellent ces routes avec credentials: 'include'. Sans le cookie de session, toute route d'admin répond 401.

Sur cette page