---
name: project-referentiel-plateformes
description: "Système référentiel commun pour les plateformes — architecture, tables, champs héritables, mécanismes de sync admin→user"
metadata: 
  node_type: memory
  type: project
  originSessionId: 7f63e6b8-eac0-45e1-bbd4-3fad774e7e8d
---

# Référentiel des plateformes

Fonctionnalité permettant à l'admin de gérer un référentiel commun (`plateformes_referentiel`) dont les utilisateurs héritent lors de la création de leurs plateformes.

**Why:** Centraliser les données communes (domiciliation, fiscalité, catégories) pour éviter la saisie répétée et garantir la cohérence entre tous les comptes utilisateurs.

**How to apply:** Toujours maintenir la cohérence entre les deux tables lors d'évolutions de schéma. Voir aussi la règle dans CLAUDE.md §7.

---

## Tables DB

### `plateformes_referentiel`
id, nom (UNIQUE), url, domiciliation, fiscalite, taux_fiscalite_locale, type_produit_fiscal, logo_filename, **methode_remboursement**, **type_pret_defaut**, **freq_interets_defaut**, description, created_at, updated_at

**Note :** `type_investissement` et `secteur` existent encore en DB mais ne sont plus utilisés dans le code (remplacés par categories_inv/secteurs_inv). `duree_defaut` et `taux_defaut` de `plateformes` ont aussi été supprimés du code (colonnes DB conservées).

### `referentiel_categories`
referentiel_id FK + categorie_nom TEXT (string, pas FK vers categories_plateforme — les catégories user sont scoped)

### `referentiel_notation`
id, referentiel_id FK, nom, type, valeurs (JSON), min_val, max_val, description, ordre, created_at

### Colonnes ajoutées à `plateformes`
- `referentiel_id INTEGER REFERENCES plateformes_referentiel(id) ON DELETE SET NULL`
- `overridden_fields TEXT NOT NULL DEFAULT '[]'` — JSON array des champs modifiés par l'user

---

## Champs héritables scalaires (HERITABLE_FIELDS)

```js
['nom', 'url', 'domiciliation', 'fiscalite', 'taux_fiscalite_locale', 'type_produit_fiscal', 'logo_filename', 'icone_filename', 'methode_remboursement', 'type_pret_defaut', 'freq_interets_defaut']
```

Définis dans `backend/src/routes/plateformes.js`. Identiques dans `referentiel.js` (PUSHABLE, sans `icone_filename`).

**Héritage tags (catégories/secteurs d'investissement) :** mécanisme séparé via merge — voir [[project-categories-secteurs-inv-heritage]].

---

## Routes backend

### Admin — `/api/referentiel` (requireAdmin)
- `GET /` — liste avec nb_plateformes_liees
- `POST /` — créer une entrée
- `PUT /:id` — modifier
- `DELETE /:id` — supprimer (délie les plateformes)
- `GET /:id/plateformes` — plateformes liées
- `POST /:id/push` — pousse les champs vers toutes les plateformes liées ; deux modes :
  - **Douce** (défaut, `force` absent) : respecte `overridden_fields`, ignore les champs modifiés par l'user
  - **Forcée** (`{ force: true }`) : écrase tous les champs et réinitialise `overridden_fields = '[]'` sur chaque plateforme
- `GET /export` — export ZIP (json + images)
- `POST /import-zip` — import ZIP avec résolution des tags par nom
- **⚠️ Routes statiques (/export, /import-zip) TOUJOURS avant `/:id`**

### Admin — `/api/admin`
- `GET /plateformes-orphelines` — plateformes sans referentiel_id, enrichies d'une suggestion de liaison (Levenshtein ≥ 80%)
- `POST /plateformes-orphelines/:id/importer` — crée une entrée référentiel depuis la plateforme
- `POST /plateformes-orphelines/:id/lier` — liaison directe à un référentiel existant sans import

### User — `/api/plateformes`
- `GET /referentiel-list` — lecture seule du référentiel (requireAuth, pas admin)
- `POST /:id/reset` — réinitialise les champs héritables depuis le référentiel, vide overridden_fields

---

## Logique frontend

### Settings.jsx
- Dropdown "Basé sur le référentiel" en tête du formulaire de création → pré-remplit champs scalaires
- `referentiel_id` transmis au POST
- Formulaire d'édition : bandeau indigo si lié + badge "hérité" par champ + bouton "Réinitialiser au référentiel"
- `openEditPlat()` charge `referentiel_id`, `referentiel_nom`, `overridden_fields`, `inherited_cat_ids`, `inherited_sect_ids`
- Bandeau affiche : `{N} champ(s) hérité(s)` + `+ catégories & secteurs` si applicable
- `inheritedCount` basé sur les 10 champs scalaires heritables
- InvSelect catégories/secteurs reçoit `inheritedIds` → items hérités toujours cochés + désactivés + badge "Réf"

### Admin.jsx (AdminPlateformes)
- Section `referentiel` : CRUD + menu ⋮ (Modifier / Pousser douce / Pousser forcée / Supprimer)
- Formulaire référentiel inclut : méthode de remboursement, type de prêt défaut, périodicité intérêts défaut
- Section `orphelines` : badge similarité ambre + bouton "Lier" / "Importer"

---

## Algorithme similarité noms (admin.js)

Levenshtein normalisé, insensible à la casse et aux accents, seuil 80%.
`similarity(a, b) = 1 - levenshtein(normalize(a), normalize(b)) / max(len(a), len(b))`
