# Cadrage Architecture — Lignes de Facturation (`billing_lines`)

## Contexte

Aujourd'hui, tout repose sur la table `declarations_devis` :
- Source du CA commercial
- Support de la facturation Pennylane (acompte, solde, avoir)
- Répartition par entité analytique (OPECO, Formation, Acquisition)
- Lien avec les projets et opérations

Quand une déclaration doit être éclatée (par dates, par PDV, par entité), on crée des "enfants" dans la même table avec `parent_declaration_id`. Cela fonctionne, mais la table porte trop de responsabilités.

## Problèmes identifiés

1. **Confusion objet commercial / objet facturation** — Une déclaration est à la fois un engagement commercial (CA signé) et un support de facturation (factures Pennylane). L'éclatement post-déclaration brouille cette frontière.

2. **Double comptage structurel** — Corrigé par l'exclusion SQL des parents splits dans `v_facturation_complete` et `v_ca_signe_livre_global`, mais cette approche est fragile (tout nouveau join doit gérer le cas parent/enfant).

3. **Limites du modèle actuel** :
   - Un seul couple acompte/solde par déclaration
   - Un seul avoir par déclaration
   - Pas de suivi de cycle de vie par ligne facturable
   - La formation est un cas spécial géré par exceptions (`type_facturation_override`, `getFormationAmount`)

## Architecture cible

```
declarations_devis (objet commercial)
├── billing_lines (lignes facturables)
│   ├── pennylane_documents (factures, avoirs)
│   ├── billing_entity (entité juridique)
│   └── commercial_split (répartition CA)
├── projects (projets opérationnels)
│   └── operations (opérations)
│       └── operations_repartition_ca (CA par commercial)
```

### Table `billing_lines`

```sql
CREATE TABLE billing_lines (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  declaration_id UUID NOT NULL REFERENCES declarations_devis(id),
  
  -- Identification
  label TEXT NOT NULL,
  line_number INTEGER NOT NULL DEFAULT 1,
  
  -- Montants
  montant_ht NUMERIC(12,2) NOT NULL,
  entity_type TEXT NOT NULL DEFAULT 'OPECO', -- OPECO, FORMATION, ECOMMERCE, ACQUISITION
  
  -- Dates
  date_debut DATE,
  date_fin DATE,
  
  -- Client facturé (peut différer de la décla)
  client_facture_nom TEXT,
  client_facture_siret TEXT,
  
  -- Liens Pennylane (par ligne, pas par déclaration)
  pennylane_customer_id TEXT,
  pennylane_invoice_id TEXT,
  pennylane_invoice_status TEXT,
  pennylane_invoice_paid BOOLEAN,
  pennylane_invoice_pdf_url TEXT,
  pennylane_avoir_id TEXT,
  
  -- Statut
  status TEXT NOT NULL DEFAULT 'pending',
  -- pending, invoiced, paid, cancelled
  
  -- Répartition commerciale (héritée ou custom)
  repartition_commerciaux JSONB,
  
  -- Audit
  created_at TIMESTAMPTZ DEFAULT now(),
  created_by UUID REFERENCES auth.users(id),
  
  UNIQUE(declaration_id, line_number)
);
```

### Bénéfices

| Problème actuel | Solution billing_lines |
|---|---|
| 1 acompte + 1 solde par décla | Chaque ligne a son propre cycle Pennylane |
| Extraction Formation manuelle | La Formation est une ligne distincte dès le départ |
| Éclatement = enfants dans la même table | L'éclatement = création de N lignes facturables |
| Double comptage parent/enfant | Le CA reste sur la déclaration, la facturation sur les lignes |
| repartition_commerciaux copiée N fois | Chaque ligne peut avoir sa propre répartition |

## Plan de migration

### Phase A : Création de la table (non bloquant)
1. Créer `billing_lines` en base
2. Créer une vue `v_billing_lines` qui présente les données existantes dans le nouveau format
3. Migrer l'écran `FacturationPennylane` pour lire `v_billing_lines` au lieu de `v_facturation_complete`

### Phase B : Migration des données
1. Pour chaque déclaration sans enfants : créer 1 billing_line
2. Pour chaque déclaration avec enfants : créer 1 billing_line par enfant, rattachée au parent
3. Pour les déclarations mixtes : créer N billing_lines (1 par entité)

### Phase C : Nouveaux flux
1. La création de déclaration crée automatiquement les billing_lines correspondantes
2. L'éclatement manipule les billing_lines au lieu de créer des déclarations enfants
3. Le SplitWizard et FormationExtractDialog opèrent sur billing_lines

### Phase D : Nettoyage
1. Supprimer les colonnes Pennylane de `declarations_devis`
2. Supprimer `parent_declaration_id`, `split_index`, `split_total`
3. Supprimer `type_facturation_override`

## Risques et arbitrages

- **Migration progressive** : les phases A et B peuvent coexister avec le système actuel via des vues de compatibilité.
- **Impact sur les dashboards commerce** : aucun si le CA reste calculé depuis `declarations_devis` + `operations_repartition_ca`.
- **Impact sur Pennylane proxy** : la edge function `pennylane-proxy` devra cibler `billing_lines` au lieu de `declarations_devis`.

## Prérequis avant lancement

- [ ] Tous les éclatements et extractions Formation passent par le SplitWizard et FormationExtractDialog
- [ ] Les vues SQL excluent correctement les parents de scission (fait)
- [ ] Le CorrectionDialog est stabilisé et utilisé en production par Virginie
- [ ] Les tests de non-régression sur le CA et la facturation sont passés

## Estimation

- Phase A : 3-5 jours
- Phase B : 2-3 jours
- Phase C : 5-8 jours
- Phase D : 2-3 jours

Total estimé : 12-19 jours de développement.
