Ventes & Facturation

Référence technique du domaine Ventes & Facturation — devis, commandes, factures, encaissements, achats fournisseur, facturation électronique B2B (réforme FR 2026).

Ventes & Facturation

Périmètre : clients, devis, commandes, factures, avoirs, règlements, fournisseurs (devis/commandes/factures/règlements miroir), entités de facturation, modes de paiement, comptabilité opérationnelle et e-invoicing (réforme FR 2026/2027 — provider : Agicap).

Les écrans vivent sous /workspace/<ressource> (et non /workspace/sales/<ressource> — convention retenue à l'implémentation). Routes API : /api/workspace/sales/*, /api/workspace/purchases/*, /api/workspace/accounting/*, /api/workspace/einvoicing/*. Source : docs/10-domain-sales-billing.md.

Vocabulaire & entités

TermeEntitéDéfinition
ClientCustomerEntité acheteuse rattachée à une Company.
FournisseurSupplierEntité vendeuse rattachée à une Company.
Entité de facturationBillingEntityEntité légale émettrice (ex. Pulse Group SAS). Une org peut en avoir plusieurs.
DevisQuote / QuoteLineProposition commerciale chiffrée ; numéro alloué à la création.
CommandeOrder / OrderLineEngagement client ferme ; issu d'une conversion de devis ou libre.
FactureInvoice / InvoiceLineDocument légal ; numéro alloué à l'émission (DRAFT → ISSUED).
AvoirCreditNoteFacture négative ; numérotation séparée (AV-YYYY-NNN).
RèglementPaymentEncaissement client ; alloué à une ou plusieurs factures.
Numéro légalInvoice.numberSéquence sans trou, immuable, par (BillingEntity, type, year).
PA (Plateforme Agréée)Opérateur fiscal (Agicap) émettant/recevant les e-factures via Peppol.
PPFPortail Public de Facturation — annuaire destinataires + concentrateur fiscal.
Factur-XFormat hybride PDF/A-3 + XML CII embarqué (EN 16931).
E-reportingEReportingSubmissionTransmission des données B2C / encaissements hors e-invoicing.
3-way matchRapprochement commande + PV réception + facture fournisseur.
Facture fournisseurSupplierInvoiceUpload PDF + OCR ; qualifiée analytiquement (nature, exercice, contrat).
Règlement fournisseurSupplierPaymentSortie vers fournisseur ; enregistré sur la fiche SupplierInvoice.

Le modèle complet est dans docs/04-data-model.md §8. La comptabilité analytique (plan comptable, nature de prestation, clôture FNP/CCA/CAP) fait l'objet d'un domaine dédié : docs/23-domain-accounting.md.

Écrans

ÉcranRouteContenu
Dashboard ventes/workspace/salesKPI CA MTD/YTD, DSO, alertes devis/factures en retard.
Liste clients/workspace/customersDataTable + encours TTC + CA YTD + DSO.
Fiche client…/customers/[id]Synthèse KYB, devis, commandes, factures, contrats LLD, conditions.
Liste devis/workspace/quotesDataTable + kanban (Drafts / Envoyés / Acceptés / Convertis).
Création devis/workspace/quotes/newWizard 5 étapes : client → BillingEntity → lignes → conditions → envoi.
Fiche devis…/quotes/[id]Lignes éditables si DRAFT, envoi, conversion commande, PDF.
Page publique devis/q/[token]Acceptation / refus client via Quote.publicToken (hors auth).
Liste commandes/workspace/ordersDataTable + statuts CONFIRMED → SHIPPED → RECEIVED → INVOICED.
Fiche commande…/orders/[id]Lignes, tracking expédition, génération facture.
Liste factures/workspace/invoicesDataTable + statut e-invoicing Agicap, actions de masse.
Création facture/workspace/invoices/newDepuis commande, contrat LLD ou libre ; aperçu Factur-X.
Fiche facture…/invoices/[id]Timeline e-invoicing, règlements, avoirs, re-soumission Agicap.
Liste règlements/workspace/paymentsLettrage manuel ou auto ; import bancaire CSV/EBICS.
Fournisseurs/workspace/suppliersMiroir module clients.
Factures fournisseur/workspace/supplier-invoicesUpload PDF + OCR + 3-way match + affectation analytique.
E-reporting/workspace/einvoicing/ereportingGénération DRAFT + soumission périodique à Agicap.
Soumissions e-invoice/workspace/einvoicing/submissionsDataTable cross-factures paginée, filtres statut/provider.
Paramètres facturation/workspace/admin/settings/billingBillingEntities, modes de paiement, templates PDF, numérotation, Agicap.

Modèle de données (points clés)

  • Invoice.number : alloué sous verrou consultatif Postgres (pg_advisory_xact_lock) à la transition DRAFT → ISSUED. Jamais avant. Test de concurrence validé : 12 émissions parallèles → FAC-1FAC-12, sans trou ni doublon.
  • Format numéro : {prefix}{YYYY}{sequence:6} — ex. FAC-2026-000123. Reset annuel optionnel par BillingEntity.
  • Invoice.facturXProfile : stocké à l'émission (audit). PDF/A-3 + XML CII embarqué généré via xmlbuilder2 ; validation XSD via libxmljs2.
  • EInvoiceSubmission : relation 1-N avec Invoice (plusieurs tentatives, champ attemptNumber). Contrainte @@unique([invoiceId, attemptNumber]).
  • SupplierInvoice.accountingCodeId + fiscalYear : contrôle bloquant pour la clôture — une facture fournisseur validée doit impérativement porter ces deux champs.
  • SupplierInvoiceAllocation : ventilation multi-contrats d'une charge réseau — la somme des lignes doit égaler totalHt de la facture.
  • EReportingSubmission : contrainte d'unicité (organizationId, yearMonth, type) ; statuts DRAFT → SUBMITTED → ACCEPTED / REJECTED.
  • Quote.publicToken : clé signée pour la page d'acceptation publique /q/[token] ; hors authentification.
  • SupplierEInvoiceReceipt : idempotence à la réception inbound — dédup par (provider, externalInvoiceId).

API

Ventes

MéthodeRoutePermission
GET/api/workspace/sales/quotessales.quote:read
POST/api/workspace/sales/quotessales.quote:create
PATCH/api/workspace/sales/quotes/[id]sales.quote:update
POST…/quotes/[id]/sendsales.quote:send
POST…/quotes/[id]/acceptsales.quote:update
POST…/quotes/[id]/convertsales.quote:convert
GET…/quotes/[id]/pdfsales.quote:read
GET/api/workspace/sales/orderssales.order:read
POST/api/workspace/sales/orderssales.order:create
POST…/orders/[id]/shipsales.order:update
POST…/orders/[id]/invoicesales.invoice:create
GET/api/workspace/sales/invoicessales.invoice:read
POST/api/workspace/sales/invoicessales.invoice:create
POST…/invoices/[id]/issuesales.invoice:issue
POST…/invoices/[id]/cancelsales.invoice:cancel
GET…/invoices/[id]/factur-xsales.invoice:read
GET…/invoices/[id]/validate-fr2026sales.invoice:read
POST…/invoices/[id]/credit-notesales.invoice:credit
POST…/invoices/[id]/remindersales.invoice:issue
POST…/invoices/[id]/resubmit-einvoicesales.invoice:issue
POST/api/workspace/sales/paymentssales.payment:create
POST…/payments/importsales.payment:create
POST…/payments/reconcilesales.payment:reconcile

Achats (miroir)

MéthodeRoutePermission
GET/api/workspace/purchases/supplierspurchasing.supplier:read
POST/api/workspace/purchases/invoicespurchasing.invoice:create
POST…/invoices/[id]/validatepurchasing.invoice:update
PATCH…/invoices/[id]/allocateaccounting.allocation:update
POST…/invoices/uploadpurchasing.invoice:create
POST/api/workspace/purchases/paymentspurchasing.payment:create

Facturation électronique (Agicap)

MéthodeRouteAuth
POST/api/workspace/invoices/[id]/e-submitsales.invoice:issue
GET/api/workspace/invoices/[id]/e-lifecyclesales.invoice:read
POST/api/workspace/einvoicing/ereporting/generatebilling.export:download
POST/api/workspace/einvoicing/ereporting/[id]/submitbilling.export:download
GET/api/workspace/einvoicing/submissionssales.invoice:read
POST/api/webhooks/einvoicing/agicap/inboundSignature HMAC
POST/api/webhooks/agicapSignature HMAC

Exemple de référence d'endpoint :

POST/api/workspace/sales/invoices/[id]/issueAuth

Valide un brouillon et émet la facture : alloue le numéro légal sous advisory lock, vérifie les mentions FR 2026, génère le PDF Factur-X, déclenche la soumission Agicap. Retourne 422 avec liste détaillée si les mentions obligatoires sont incomplètes.

Corps (JSON)

sendEmail
boolean
Envoyer la facture par email au client juste après émission.

Requête

curl -s -X POST "$API/api/workspace/sales/invoices/$ID/issue" \
  -H "Content-Type: application/json" -H "Cookie: $SESSION" \
  -d '{"sendEmail": true}'

Réponse

{
  "id": "inv_…",
  "number": "FAC-2026-000042",
  "status": "ISSUED",
  "facturXProfile": "EN16931",
  "issuedAt": "2026-06-16T10:00:00Z"
}

Comptabilité opérationnelle

MéthodeRoutePermission
GET/api/workspace/accounting/journal-salesbilling.export:download
GET/api/workspace/accounting/journal-purchasesbilling.export:download
GET/api/workspace/accounting/balance-customersbilling.export:download
GET/api/workspace/accounting/vat-summarybilling.export:download
GET/api/workspace/accounting/export?format=fec|sage|cegid|pennylanebilling.export:download

Workflows

Cycle vente standard

Opportunity (CRM)
   │
   └─→ Quote (DRAFT) → SENT → ACCEPTED → CONVERTED
                                              │
                                         Order (CONFIRMED)
                                              │
                                         SHIPPED → RECEIVED
                                              │
                                         Invoice (DRAFT) → ISSUED → PAID

À l'émission (DRAFT → ISSUED) : advisory lock, numérotation légale irréversible, génération Factur-X, contrôle mentions FR 2026, soumission Agicap.

Numérotation légale (garde-fou)

Séquence par (BillingEntity, type, year). Le numéro est consommé une seule fois, à la transition vers ISSUED. Toute tentative d'émission concurrente attend la libération du verrou (pg_advisory_xact_lock). Reset annuel optionnel. La suppression d'une facture ISSUED est interdite — seule une annulation avec création d'avoir total est possible.

Facturation électronique B2B — réforme FR

ÉchéanceObligation
1ᵉʳ septembre 2026Réception obligatoire pour toutes les entreprises ; émission pour grandes entreprises et ETI.
1ᵉʳ septembre 2027Émission obligatoire pour PME et TPE.

Pulse ERP vise la conformité complète (émission + réception + e-reporting) au 1ᵉʳ septembre 2026, indépendamment du seuil par BillingEntity.

Workflow émission (Agicap, Phase 7 — livré) :

  1. Facture ISSUED → génération Factur-X (XML CII + PDF/A-3).
  2. Contrôle bloquant des mentions obligatoires FR 2026 (SIREN client, adresse livraison, nature opération, option TVA sur débits).
  3. Résolution du destinataire (SIREN/SIRET → identifiant Agicap/Peppol).
  4. Soumission API Agicap → EInvoiceSubmission.providerInvoiceId.
  5. Suivi cycle de vie via webhook HMAC POST /api/webhooks/agicap — statuts : SUBMITTED → RECEIVED_BY_PDP → DEPOSITED → RECEIVED_BY_RECIPIENT → APPROVED / REFUSED / IN_DISPUTE / PAID / REJECTED_BY_PDP.
  6. En cas de rejet/refus : re-soumission via POST …/resubmit-einvoice (incrémente attemptNumber).

Workflow réception inbound : webhook POST /api/webhooks/einvoicing/agicap/inbound → parser CII (cii-parser.ts) → matching fournisseur par SIREN → création SupplierInvoice status RECEIVED. Idempotence via SupplierEInvoiceReceipt.

Relances impayés

Job nocturne invoice-reminder :

  • J-3 avant échéance → relance amicale.
  • J+1 → 1ʳᵉ relance ferme.
  • J+15 → 2ᵉ relance avec frais.
  • J+30 → mise en demeure (PDF généré).
  • J+45 → escalade direction + suggestion contentieux.

Suivi : Invoice.lastReminderSentAt, reminderCount. Désactivable par client.

E-reporting périodique

POST /api/workspace/einvoicing/ereporting/generate — body { yearMonth, type } (types : TRANSACTIONS, PAYMENTS, B2C). Soumission via …/[id]/submit. Contrainte d'unicité (organizationId, yearMonth, type) évite les doubles envois.

Règles métier

  • Numérotation sans trou, immuable, par BillingEntity — obligation légale FR. Advisory lock Postgres à chaque émission.
  • Date facture = date d'émission = date où la facture passe ISSUED. Non modifiable après.
  • TVA multi-taux dans une facture (5,5 %, 10 %, 20 %). Auto-liquidation pour clients intra-UE (mention obligatoire + vérification VIES).
  • Facture > 5 € HT : mentions légales obligatoires (SIRET, N° TVA, conditions règlement, taux pénalité, indemnité 40 €).
  • Avoir partiel : total avoirs ne peut pas dépasser le total facture. Avoir total → facture passe CANCELED.
  • Paiement : ne peut pas dépasser le montant dû.
  • Suppression facture ISSUED interdite ; soft delete sur DRAFT uniquement.
  • 3-way match fournisseur : refus de paiement si écart > seuil (5 % ou montant absolu configurable).
  • SupplierInvoice validée sans accountingCodeId ou fiscalYear : bloquant pour la clôture comptable.
  • Ventilation SupplierInvoiceAllocation : somme des lignes doit égaler totalHt de la facture.

KPIs

CA HT MTD, YTD, comparatif N-1 · panier moyen · DSO global et par client · % factures payées dans les délais · encours > 30/60/90 jours · taux d'acceptation devis · cycle moyen Quote → Order → Invoice → Paid · TVA collectée / déductible / nette · marge brute par produit.

Notifications

ÉvénementCanalDestinataire
Devis envoyéEmailClient
Devis accepté (lien public)In-app + emailCommercial
Facture émiseEmail (avec PDF)Client
Facture proche échéance (J-3)EmailClient (si activé)
Facture en retard (J+1)EmailClient + commercial
Facture > 30j retardIn-app + emailComptable + manager
Avoir émisEmailClient
Paiement reçuIn-app + emailComptable
Facture fournisseur reçue (Agicap)In-appComptable
Facture rejetée / refusée (Agicap)In-app + emailComptable + commercial
E-reporting transmis / en échecIn-appComptable
3-way match KOIn-appComptable