Aller au contenu principal

Inventaire : Module de Facturation Actuel

Ce document liste tous les endpoints, modèles DB, et flux existants du module de facturation avant l'implémentation du plan d'amélioration.

Date de création : 2024-12-19
But : Comprendre l'état actuel avant refactoring


1. Endpoints API Existants

Controller : InvoicesController (/invoices)

  • GET /invoices - Liste toutes les factures de l'utilisateur (paginé)
  • POST /invoices - Créer une nouvelle facture
  • GET /invoices/:id - Récupérer une facture par ID
  • PUT /invoices/:id - Mettre à jour une facture
  • GET /invoices/:id/export?format=pdf|docx - Exporter une facture (PDF ou Word)
  • GET /invoices/:id/pdf - Générer le PDF d'une facture
  • POST /invoices/:id/preview-email - Prévisualiser l'email de facture
  • POST /invoices/:id/send-email - Envoyer une facture par email

Controller : QuotesInvoicesController (/sessions/:sessionId/quotes-invoices)

Quotes

  • GET /sessions/:sessionId/quotes-invoices/quotes - Liste les devis d'une session
  • GET /sessions/:sessionId/quotes-invoices/quotes/:id - Récupérer un devis
  • POST /sessions/:sessionId/quotes-invoices/quotes - Créer un devis
  • PUT /sessions/:sessionId/quotes-invoices/quotes/:id - Mettre à jour un devis
  • DELETE /sessions/:sessionId/quotes-invoices/quotes/:id - Supprimer un devis
  • GET /sessions/:sessionId/quotes-invoices/quotes/:id/pdf - PDF du devis
  • POST /sessions/:sessionId/quotes-invoices/quotes/:id/preview-email - Prévisualiser email devis
  • POST /sessions/:sessionId/quotes-invoices/quotes/:id/send-email - Envoyer devis par email

Invoices (via session)

  • GET /sessions/:sessionId/quotes-invoices/invoices - Liste les factures d'une session
  • POST /sessions/:sessionId/quotes-invoices/invoices - Créer une facture pour une session
  • GET /sessions/:sessionId/quotes-invoices/invoices/:id - Récupérer une facture
  • PUT /sessions/:sessionId/quotes-invoices/invoices/:id - Mettre à jour une facture
  • DELETE /sessions/:sessionId/quotes-invoices/invoices/:id - Supprimer une facture
  • GET /sessions/:sessionId/quotes-invoices/invoices/:id/pdf - PDF de la facture

Controller : QuotesController (/quotes)

  • GET /quotes - Liste toutes les quotes de l'utilisateur (paginé)
  • POST /quotes - Créer une quote
  • GET /quotes/:id - Récupérer une quote
  • PUT /quotes/:id - Mettre à jour une quote
  • DELETE /quotes/:id - Supprimer une quote

2. Modèles de Base de Données

Table : invoices

Migration : 0066_create_quotes_and_invoices/up.sql

CREATE TABLE invoices (
id UUID PRIMARY KEY,
owner_id UUID NOT NULL REFERENCES users(id),
session_id UUID REFERENCES sessions(id),
quote_id UUID REFERENCES quotes(id),
contact_id UUID REFERENCES contacts(id), -- Ajouté dans 0083
title TEXT NOT NULL,
description TEXT,
amount DECIMAL(10, 2) NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'DRAFT' CHECK (status IN ('DRAFT', 'SENT', 'PAID', 'OVERDUE')),
due_date DATE,
paid_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

Index :

  • invoices_owner_idx sur owner_id
  • invoices_session_idx sur session_id
  • invoices_quote_idx sur quote_id
  • invoices_status_idx sur status

Statuts actuels : DRAFT, SENT, PAID, OVERDUE

Table : invoice_items

Migration : 0082_create_invoice_items/up.sql

CREATE TABLE invoice_items (
id UUID PRIMARY KEY,
invoice_id UUID NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
item_type TEXT NOT NULL CHECK (item_type IN ('BLANK', 'TEXT', 'SESSION_TYPE', 'DISCOUNT')),
description TEXT,
quantity DECIMAL(10, 2) NOT NULL DEFAULT 1.0,
price_with_tax DECIMAL(10, 2) NOT NULL DEFAULT 0,
vat_percentage DECIMAL(5, 2) NOT NULL DEFAULT 0,
price_without_tax DECIMAL(10, 2) NOT NULL DEFAULT 0,
discount_percentage DECIMAL(5, 2) NOT NULL DEFAULT 0,
total DECIMAL(10, 2) NOT NULL DEFAULT 0,
display_order INTEGER NOT NULL DEFAULT 0,
user_session_type_id UUID REFERENCES user_session_types(id),
discount_amount DECIMAL(10, 2),
discount_type TEXT CHECK (discount_type IN ('PERCENTAGE_OF_TOTAL', 'FIXED_WITH_TAX', 'FIXED_WITHOUT_TAX')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

Table : stripe_payments

Migration : 0084_create_stripe_integration/up.sql

Champs clés :

  • invoice_id UUID REFERENCES invoices(id)
  • stripe_payment_intent_id TEXT
  • amount DECIMAL(10, 2)
  • currency TEXT DEFAULT 'eur'
  • status TEXT (succeeded, pending, failed, etc.)

Table : paypal_payments

Migration : 0093_create_paypal_integration/up.sql

Champs clés :

  • invoice_id UUID REFERENCES invoices(id)
  • paypal_order_id TEXT UNIQUE
  • amount DECIMAL(10, 2)
  • currency TEXT DEFAULT 'EUR'
  • status TEXT (COMPLETED, CREATED, SAVED, etc.)

Table : user_company

Migration : 0041_create_user_company_table/up.sql

Champs pertinents pour facturation :

  • company_name TEXT NOT NULL
  • siren TEXT
  • siret TEXT
  • company_street TEXT
  • company_zipcode TEXT
  • company_city TEXT
  • company_country TEXT

Table : audit_logs

Migration : 0101_create_audit_logs/up.sql

Structure :

  • action TEXT (CREATE, UPDATE, DELETE, etc.)
  • entity_type TEXT (INVOICE, QUOTE, etc.)
  • entity_id UUID
  • resource_owner_id UUID
  • metadata JSONB
  • created_at TIMESTAMPTZ

3. Flux Actuels

3.1. Flux de Création de Facture

  1. Création (POST /invoices ou /sessions/:id/quotes-invoices/invoices)

    • Validation via createInvoiceSchema (Zod)
    • Vérification ownership (session/contact/quote)
    • Insertion dans invoices
    • Création des invoice_items si fournis
    • Recalcul automatique du amount depuis les items
    • Audit log : CREATE avec entityType: 'INVOICE'
  2. Modification (PUT /invoices/:id)

    • Validation via updateInvoiceSchema
    • Vérification ownership
    • Mise à jour de l'invoice
    • Mise à jour des items (suppression/recréation)
    • Recalcul du amount
    • Audit log : UPDATE
  3. Génération PDF (GET /invoices/:id/pdf)

    • Génération HTML via getInvoicePdfHtml()
    • Conversion en PDF via PdfService
    • Upload vers R2 (Cloudflare)
    • Retour d'une signed URL
    • Note : PDF généré à la demande, pas de stockage systématique

3.2. Flux de Paiement

Via Stripe

  1. Création Payment Intent (POST /stripe/payments/invoices)

    • Création dans Stripe
    • Enregistrement dans stripe_payments
    • Retour clientSecret pour le frontend
  2. Webhook Stripe (POST /stripe/webhooks)

    • Écoute événements payment_intent.succeeded
    • Mise à jour stripe_payments.status
    • Mise à jour invoices.status = 'PAID'
    • Mise à jour invoices.paid_at

Via PayPal

  1. Création Order (POST /paypal/payments/invoices)

    • Création dans PayPal
    • Enregistrement dans paypal_payments
    • Retour approvalUrl
  2. Webhook PayPal (POST /paypal/webhooks)

    • Écoute événements PAYMENT.CAPTURE.COMPLETED
    • Mise à jour paypal_payments.status
    • Mise à jour invoices.status = 'PAID'
    • Mise à jour invoices.paid_at

Limitations actuelles :

  • Un seul paiement par invoice (pas de paiements partiels)
  • Pas de calcul de balance_due
  • Statut PAID = paiement total uniquement

3.3. Flux d'Email

  1. Prévisualisation (POST /invoices/:id/preview-email)

    • Génération HTML de l'email
    • Remplissage des variables
    • Retour HTML pour prévisualisation
  2. Envoi (POST /invoices/:id/send-email)

    • Validation destinataires
    • Génération PDF si nécessaire
    • Envoi via Gmail API
    • Enregistrement dans scheduled_emails si planifié
    • Tracking dans email_tracking
    • Mise à jour invoices.status = 'SENT' si applicable

4. Services Backend

Services Principaux

  • QuotesInvoicesService - Service principal orchestrateur
  • QuotesInvoicesInvoicesCrudService - CRUD invoices
  • QuotesInvoicesQuotesCrudService - CRUD quotes
  • QuotesInvoicesItemsService - Gestion des items
  • QuotesInvoicesPdfService - Génération PDF
  • QuotesInvoicesEmailService - Envoi emails
  • StripePaymentsService - Intégration Stripe
  • PaypalPaymentService - Intégration PayPal

Calculs Actuels

  • Frontend : frontend/src/utils/document-totals.utils.ts

    • Fonction calculateDocumentTotals(items)
    • Calcul sous-total, taxes, réductions, total
  • Backend : QuotesInvoicesItemsService

    • Recalcul amount depuis items lors création/mise à jour
    • Pas de wrapper Decimal (utilise Number())

5. Points d'Intégration Identifiés

Webhooks Externes

  • Stripe : /stripe/webhooksStripeWebhooksController
  • PayPal : /paypal/webhooksPaypalWebhooksController

Points d'Extension

  • Audit logs : @AuditLog() decorator existant
  • PDF generation : PdfService avec support R2
  • Email : GmailService intégré
  • Storage : StorageService (R2/S3)

6. Limitations et Manques Identifiés

Immutabilité

  • ❌ Factures modifiables même après SENT
  • ❌ Pas de snapshots figés à l'émission
  • ❌ PDF régénéré à chaque demande (pas de hash)

Numérotation

  • ❌ Pas de numérotation séquentielle
  • ❌ Format actuel : YYYY-{8 premiers caractères ID} (non séquentiel)

Compliance

  • ❌ Pas de validation mentions obligatoires
  • ❌ Pas de vérification SIREN/SIRET
  • ❌ Pas de contrôle des mentions légales (pénalités, indemnité 40€)

Avoirs

  • ❌ Pas de table credit_notes
  • ❌ Pas de support pour avoirs

Paiements

  • ❌ Pas de paiements partiels
  • ❌ Pas de table payments unifiée
  • ❌ Pas de calcul balance_due

Export Comptable

  • ❌ Pas d'export comptable
  • ❌ Pas de mapping comptes

E-invoicing

  • ❌ Pas de champs préparation e-invoicing
  • ❌ Pas de stockage facture structurée

7. Fichiers Clés à Modifier

Services

  • backend/src/quotes-invoices/quotes-invoices-invoices-crud.service.ts
  • backend/src/quotes-invoices/quotes-invoices-items.service.ts
  • backend/src/quotes-invoices/invoices.controller.ts
  • backend/src/stripe/stripe-webhooks.service.ts
  • backend/src/paypal/paypal-webhooks.controller.ts

DTOs

  • backend/src/quotes-invoices/dto/create-invoice.dto.ts
  • backend/src/quotes-invoices/dto/update-invoice.dto.ts

Types

  • backend/src/_generated/types.gen.ts (regénéré depuis OpenAPI)
  • backend/src/db/database.types.ts (types Kysely)

8. Migration de Données Nécessaire

Factures Existantes

  • DRAFT → reste DRAFT
  • SENT, PAID, OVERDUEISSUED
  • Générer numéros rétroactifs pour factures émises
  • issued_at = created_at pour factures existantes

Paiements Existants

  • Copier stripe_paymentspayments
  • Copier paypal_paymentspayments
  • Recalculer balance_due pour toutes les invoices
  • Mettre à jour statuts (PARTIALLY_PAID si applicable)

9. Notes d'Implémentation

  • Les tests existants dans backend/src/__tests__/quotes-invoices/ doivent être adaptés
  • L'immutabilité nécessitera des guards API et potentiellement des triggers DB
  • La numérotation séquentielle nécessite une table de séquences avec locks
  • Le système d'audit existant peut être enrichi avec les nouveaux événements