# PROJECT.md — ERP Immobilier Interne

> Fichier de contexte à coller en début de chaque session Claude.
> Mettre à jour au fil de l'avancement du projet.

---

## Contexte général

- **Type** : ERP métier interne (pas un produit à vendre)
- **Secteur** : Promotion immobilière
- **Objectif** : Remplacer Pegao (trop cher en développements spécifiques)
- **Équipe dev** : DSI seul, ancien développeur web (HTML, PHP, JS)
- **Horizon** : 6 à 12 mois pour les premiers modules en production

---

## Stack technique

| Couche | Technologie |
|---|---|
| Backend | Laravel 11 (PHP) |
| Base de données | PostgreSQL managé |
| Cache / Files | Redis managé |
| Frontend | Vue.js 3 + Inertia.js |
| CSS | Tailwind CSS |
| Composants UI | PrimeVue |
| Authentification | SSO Microsoft 365 via Laravel Socialite |
| Intégration M365 | Microsoft Graph API |
| Hébergement | OVHcloud Public Cloud (France) |
| IA intégrée | API Claude (Anthropic) |
| Versioning | GitHub (repo privé) |
| IDE | Cursor |

### ⚠️ Conventions front à respecter (notes techniques permanentes)

- **Ziggy n'est PAS installé** dans le projet. Le helper `route()` côté Vue retourne `undefined`.
- Pour tout appel HTTP depuis Vue : **toujours utiliser des URLs directes** (`/api/...`, `/programmes/{id}/...`).
- **Jamais** d'appel à `route('...')` côté Vue.
- 👉 À mentionner systématiquement dans les prompts Cursor qui touchent du front Vue avec endpoints.

---

## Architecture d'hébergement

```
OVHcloud Public Cloud (🇫🇷 France — Roubaix / Gravelines)
├── Instance B2-7 (2 vCores, 7GB RAM)  → Laravel + Redis (~25€/mois)
├── PostgreSQL managé                   → Base de données (~25€/mois)
├── Redis managé                        → Cache et jobs (~10€/mois)
└── Object Storage                      → Exports, backups (~5€/mois)
Total hébergement                       → ~65€/mois

Microsoft 365 (existant)
├── Entra ID            → Authentification SSO
└── SharePoint          → GED (documents programmes)
```

> Les documents restent sur SharePoint. Pas de GED custom à développer.
> OVHcloud gère automatiquement : backups PostgreSQL, SSL, mises à jour OS.

### ⚠️ Contraintes infra OVH constatées (mai 2026)

- **Sorties HTTPS depuis SSH/CLI bloquées** sur l'hébergement OVH (notamment `graph.facebook.com`, `api.intacct.com`).
- Conséquence : les commandes artisan qui appellent des APIs externes ne fonctionnent pas en CLI.
- **Workaround systématique** : exposer toute commande artisan utile via un **endpoint admin équivalent** qui passe par la voie HTTP PHP-FPM (non bloquée).
- Pattern type : `php artisan x:y` ↔ route `POST /admin/x/y` qui appelle le même service.
- Limite upload PHP plafonnée à 128M sur cluster mutualisé (ticket OVH en cours pour les AO > 350 Mo).

---

## Budget mensuel estimé

| Poste | Prix/mois |
|---|---|
| OVHcloud Public Cloud | ~65€ |
| API Claude (extraction factures) | ~20-50€ |
| Cursor (développement) | ~20€ |
| GitHub (privé) | Gratuit |
| **Total** | **~105-135€/mois** |
| **Pegao actuel** | **2 400€/mois** |
| **Économie mensuelle** | **~2 265€** |
| **Économie annuelle** | **~27 000€** |

---

## Portabilité et indépendance

- **Code** : sur GitHub, exportable à tout moment
- **Données** : PostgreSQL standard, export CSV/JSON/Excel natif depuis l'app
- **Hébergeur** : changement possible en quelques heures (pg_dump + git clone)
- **Aucun enfermement propriétaire** : stack 100% open source standard
- **Reprise par une ESN** : Laravel est une stack connue de tous les prestataires

---

## Prototype Lovable — acquis réutilisables

> Un collègue a réalisé un prototype React/TypeScript (Vite + shadcn/ui) sur Lovable.
> Ce n'est pas une base de code à migrer (stack différente, données en mémoire, pas de backend),
> mais c'est une mine d'information pour accélérer le développement Laravel.

### Repo : `facturationenvol-main` (React + TypeScript + shadcn/ui)

### Ce qui est directement exploitable

**Logique métier validée (fichier `src/lib/calculations.ts`)** — à transposer en PHP/Laravel :
```typescript
// Montant total marché avec avenants
totalMarcheHT(marche, avenants) = marche.montant_marche_ht + SUM(avenants.montant_ht)

// Net TTC d'une situation après RG et compte prorata
situationNetTTC(s) = montant_ht * (1 - rg_pct/100) * (1 - cp_pct/100) * (1 + tva/100)

// Reste à régler HT
resteAReglerHT = totalMarcheHT - SUM(situations.montant_ht)

// % avancement
avancementPct = SUM(situations.montant_ht) / totalMarcheHT * 100

// Delta marge TMA
tmaDeltaMargeTTC = facture_client_ttc - facture_entreprise_ttc
```

**Modèle de données confirmé (types TypeScript → migrations PostgreSQL)** — voir section "Tables clés" ci-dessous.

**Deux jeux de données réels** utilisables comme fixtures de test :
- `arboreaData.ts` — Programme ARBORÉA (Montpellier, réf. 340031-ARBOREA, 13 lots travaux + 17 lots prestataires, marchés réels)
- `louMarquesData.ts` — Programme LOU MARQUES (données similaires)

**Lots techniques réels du programme ARBORÉA** (confirmés dans le prototype) :

| Code | Libellé | Entreprise |
|---|---|---|
| 01 | Gros œuvre | ST ROCH BTP |
| 02 | Étanchéité | VINOIS |
| 03 | Men. Ext. | LES ZELLES |
| 04 | Men. Int. | BLACHERE |
| 05 | Cloisons | OCCIPLAC |
| 06 | Carrelage | ATC |
| 07 | Serrurerie | HELIX |
| 08 | Plomberie | ACLIMATIS |
| 09 | Électricité | IDEM |
| 10 | Peinture | RICCADI |
| 11 | Façades | BSA |
| 12 | Ascenseurs | ORONA |
| 13 | Espaces verts | SARIVIERE |
| P00 | Achat terrain | SERM |
| P01a | Architecte | A+ |
| P01b | Architecte intérieur | A+ (partie TORRES) |
| P02 | Assurance | SMA BTP |
| P07/P08 | Étude de sol | EGSA |
| P12 | Contrôle Technique | SOCOTEC |
| P14 | Certification NF | Cerqual |
| P15 | CSPS | SOCOTEC |
| P16/P16B | Repro | Arts Helio / Digitalis |
| P17x | Commercial | MADN, IMP'ACT, KUTCH STUDIO, UNLATCH, ECOPUB, ADIMO |

**Concessionnaires identifiés** : ENEDIS, Réseau de chaleur, AEP/EU/EP, Orange

**Pages UI validées fonctionnellement** (à transposer en Vue.js + PrimeVue) :
- Dashboard (KPIs + courbe S + alertes paiements en retard + synthèses)
- Travaux & Situations (par lot, avec avenants et barre d'avancement)
- Prestataires
- TMA / TS (Travaux Modificatifs Acquéreurs / Travaux Supplémentaires)
- Concessionnaires (VRD)
- Commercialisation (lots + dépenses communication)
- Taxes
- Plan de Trésorerie (tableau glissant N mois, recettes/dépenses, solde cumulé)
- Reste à Payer (travaux + RG + compte prorata + concessionnaires + taxes)

**Catégories TMA confirmées** : Oubli/Erreur, Modification, Prestations sup., Aléas, Transfert +, Transfert -, Offres

**Types de communication** : PUBLICITE, AGENCES, DIVERS

**Statuts commerciaux** : En stock, Réservé, Acté, Annulé

### Ce que le prototype ne couvre pas (à développer entièrement dans Laravel)
- Auth SSO Microsoft / Entra ID + groupes M365
- Backend, base de données, persistance (tout est en mémoire dans le prototype)
- Bilan financier 5 rubriques (Terrain / VRD / Construction / FG / Charges directes)
- Workflow de validation factures (NV1 → PDG → Comptable → DAF)
- Intégration Sage Intacct (synchro fournisseurs, factures, paiements)
- Intégration SharePoint / Graph API (GED + arborescence automatique)
- Code analytique PRG-{département}-{code}
- CRM acquéreurs + réservations VEFA + prescripteurs
- OCR factures via API Claude

---

## Modules à développer

| Priorité | Module | Statut | Notes |
|---|---|---|---|
| 1 | Socle technique + Auth M365 | 🔲 À faire | SSO + Graph API + migrations de base |
| 2 | CRM acquéreurs | 🔲 À faire | Très spécifique à nos process |
| 3 | Finance / bilan promoteur | 🔲 À faire | Cœur métier, à bien sécuriser |
| 4 | Marchés & Factures | 🔲 À faire | Circuit validation + synchro Intacct |
| 5 | Développement foncier | 🔲 À faire | Parcelles, promesses, faisabilité |
| 6 | Suivi chantier | 🔲 À faire | Marchés, situations de travaux |
| 7 | Livraison / SAV / GPA | 🔲 À faire | Le plus complexe, en dernier |

---

## Roadmap indicative

| Période | Objectif |
|---|---|
| M1 | Socle Laravel + Auth SSO M365 + intégration Graph API |
| M2-M3 | CRM acquéreurs (prospects → réservation → contrat VEFA) |
| M4-M5 | Finance / bilan promoteur |
| M6-M7 | Marchés & Factures + synchro Sage Intacct |
| M8-M9 | Développement foncier |
| M10-M12 | Suivi chantier (version basique) |
| Post M12 | Livraison / SAV / GPA |
| Futur | Remplacement Unlatch (CRM commercial, signature Yousign, purge AR24, portail acquéreur) |

---

## Modèle de données principal

```
SOCIÉTÉ
└── PROGRAMME
    ├── LOTS
    │   ├── GRILLES DE PRIX (historique)
    │   ├── OFFRES COMMERCIALES (temporaires)
    │   ├── ACQUÉREURS (CRM)
    │   │   └── RÉSERVATIONS / CONTRATS VEFA
    │   └── TMA (Travaux Modificatifs Acquéreurs)
    ├── BILAN FINANCIER (5 rubriques)
    │   ├── 1. TERRAIN
    │   ├── 2. VRD (Concessionnaires)
    │   ├── 3. CONSTRUCTION
    │   ├── 4. FRAIS GÉNÉRAUX
    │   └── 5. CHARGES DIRECTES
    ├── MARCHÉS (prestataires + travaux)
    │   ├── AVENANTS
    │   ├── SITUATIONS DE TRAVAUX
    │   └── FACTURES → VALIDATIONS
    ├── PRESCRIPTEURS → COMMISSIONS
    ├── ASSOCIÉS → PARTICIPATIONS → APPELS DE FONDS
    └── DOCUMENTS (SharePoint via Graph API)

FOURNISSEURS (synchronisés depuis Sage Intacct)
PRESTATIONS (référentiel lots/codes comptables)
```

---

## Référentiel des prestations (issu du fichier LISTES_LOTS_ENVOL.csv)

57 prestations organisées en 6 catégories avec codes comptables :

```sql
prestations
id, libellé, catégorie, code_prestation, description, compte_comptable

-- Catégories :
-- 1_HONORAIRES  → comptes 331xxx / 334xxx / 622xxx
-- 2_TRAVAUX     → compte 333000 (tous les lots travaux)
-- 3_CONCESSIONNAIRES → compte 332000
-- 4_TAXES       → compte 332100
-- 5_COMMERCIAL  → comptes 623xxx / 707xxx / 334xxx
```

Exemples clés :
- `101_ARCHITECTE` → 331453
- `102_MOE` → 331452
- `203_GROS_OEUVRE` → 333000
- `505_TMA` → 707201 (compte recette acquéreur)
- `Commisson` → 334402

---

## Structure du bilan financier (5 rubriques — nomenclature Flora)

```
RUBRIQUE 1 — TERRAIN
├── Achat terrain
├── Étude de sol
├── Géomètre + EDD
├── Notaire
├── Huissier
├── Diagnostics
├── Référé préventif
├── Taxe aménagement
├── Taxe archéologique
├── Taxe raccordement
├── PUP
├── Exonération taxes
└── Honoraires montage

RUBRIQUE 2 — VRD
├── ENEDIS
├── Orange (Télécom)
├── AEP (eau potable)
├── EU (eaux usées)
├── Pluvial
├── GRDF (gaz)
└── Transformateur

RUBRIQUE 3 — CONSTRUCTION
├── Travaux + VRD + Désamiantage
├── Provision imprévus
├── NF Habitat Cerqual / Label
├── BET Structure
├── BET Fluides
├── BET VRD
├── CT + Vérif + Attestation Handicap + DPE
├── SPS (CSPS)
├── MOE / OPC
├── Architecte
└── Honoraires groupe

RUBRIQUE 4 — FRAIS GÉNÉRAUX
├── Assurance
├── Frais et garanties financiers
├── Honoraires vente (libre + social)
├── Logiciels
├── Provision SAV / Juridique
├── Commissions vente
├── Frais divers
├── Divers notaires
└── Honoraires groupe

RUBRIQUE 5 — CHARGES DIRECTES
└── Publicité

RECETTES
├── Chiffre d'affaires HT (lots)
└── TMA (recettes acquéreurs)

INDICATEURS
├── Marge = Recettes - Charges
├── Honoraires groupe (séparés)
├── Marge + Honoraires
├── Taux de marge sur CA HT
└── Taux de marge avec honoraires sur CA TTC
```

**3 colonnes de comparaison par poste :**
- Étude fi bq (prévisionnel initial)
- Marchés signés (sans avenants)
- Bilan fi réel (avec avenants + facturé réel)
- Delta Étude/Signé
- Delta Étude/Bilan
- Commentaires

---

## Tables clés mises à jour (données réelles Flora + prototype Lovable)

**lots** *(enrichi)*
```sql
id, programme_id, référence, type (T2/T3/T4/T3D...),
bâtiment, étage, surface_habitable, surface_annexe,
orientation,
-- Prix et grilles
prix_acte_ttc,            -- prix figé à la réservation
statut (disponible/réservé/acté),
-- Prescripteur
prescripteur_id,
taux_commission_pct,      -- variable par lot (2.5% à 5.25%)
-- Financement acquéreur
type_financement (I/RP/investissement),
acquéreur_id,
sharepoint_folder_url
```

**lots_techniques** *(confirmé par prototype — distinction travaux / prestataires)*
```sql
id, programme_id,
code,                     -- ex: "01", "P01a", "P17b"
libelle,                  -- ex: "Gros œuvre", "Architecte"
type (travaux/prestataire/concessionnaire),
entreprise_id             -- fournisseur Intacct associé
```

**grilles_prix** *(nouveau — issu Flora : 14 versions sur 3 ans)*
```sql
id, lot_id, programme_id,
date_application,
prix_ttc,
créée_par, created_at
-- Historique complet de toutes les grilles
-- Le prix d'acte est figé à la date de réservation
```

**tma** *(enrichi — issu Flora + prototype)*
```sql
id, lot_id, acquéreur_id,
localisation,             -- ex: "SDB", "Cellier"
désignation,              -- description de la modification
prestation_id,            -- lot technique concerné
montant_facturé_entreprise_ht,
montant_facturé_entreprise_ttc,
montant_facturé_client_ht,
montant_facturé_client_ttc,
delta_marge_ttc,          -- calculé auto : client - entreprise
catégorie,                -- Oubli/Erreur | Modification | Prestations sup. | Aléas | Transfert + | Transfert - | Offres
badges,                   -- Social | Investisseur
observations,
statut (devis/validé/facturé/réglé),
marché_id,
documents_sharepoint_url
```

**ts** *(Travaux Supplémentaires — nouveau issu prototype)*
```sql
id, programme_id,
appartement,              -- référence logement concerné
nature_travaux,
lot_technique_id,
entreprise_id,
validation_client (bool),
devis_client_ht, devis_client_ttc,
facture_ent_ht, facture_ent_ttc,
catégorie,                -- même enum que TMA
motif,
avenant_num,
facture_num,
date_reglement
```

**marchés** *(enrichi)*
```sql
id, programme_id, fournisseur_id, prestation_id,
numéro_lot_technique,     -- ex: "01a - Architecte", "01 - Gros œuvre"
référence, intitulé,
type (forfait/bordereau),
montant_marché_ht,        -- montant initial
montant_total_ht,         -- marché + avenants (calculé)
taux_tva, montant_total_ttc,
date_signature, date_début, date_fin_prev,
retenue_garantie_pct,     -- 5% standard (confirmé Flora + prototype)
a_caution (bool),
montant_caution,
compte_prorata_pct,       -- 1.5% standard (confirmé prototype)
statut (en_cours/soldé/résilié),
-- Suivi calculés automatiquement
total_facturé_ht,         -- SUM(situations)
pct_avancement,           -- total_facturé / montant_total
reste_à_régler_ht,        -- montant_total - total_facturé
documents_sharepoint_url,
intacct_id, intacct_synced_at, intacct_error
```

**avenants** *(enrichi)*
```sql
id, marché_id, numéro,    -- jusqu'à 4 avenants observés sur Flora
motif, montant_ht,
tva,
date_signature, statut
```

**situations** *(confirmé prototype — jusqu'à N°26 sur Flora)*
```sql
id, marché_id, numéro,
montant_ht,
tva,
retenue_garantie_pct,     -- copié du marché à la création
compte_prorata_pct,       -- copié du marché à la création
date_facture,
date_paiement,            -- date effective du paiement
statut (émise/validée/payée/en_retard),
facture_id                -- lien vers la facture validée
```

**concessionnaire_factures** *(confirmé prototype)*
```sql
id, programme_id,
titulaire,                -- ENEDIS | Réseau de chaleur | AEP-EU-EP | Orange
type (devis/marché/acompte),
désignation,
montant_ht, tva, montant_ttc,
date_validation,
date_paiement,
delta_budget_ht           -- écart vs prévisionnel
```

**lots_commerciaux** *(confirmé prototype — vue commerciale du lot)*
```sql
id, programme_id,
numero_lot,               -- référence commerciale (A101, B203...)
type_logt,                -- T2, T3, T3D, T4...
grille_prix,              -- prix catalogue actuel TTC
prix_vente,               -- prix négocié TTC
difference,               -- calculé : prix_vente - grille_prix
statut (en_stock/réservé/acté/annulé),
tma_montant,              -- montant TMA facturé client TTC
remises_commerciales_ttc,
agence_nom,
agence_commission_ttc,
commentaires
```

**communication_depenses** *(confirmé prototype)*
```sql
id, programme_id,
rubrique (PUBLICITE/AGENCES/DIVERS),
objet,
montant,
tva_incluse (bool),
date
```

**postes_budgétaires** *(enrichi — nomenclature Flora)*
```sql
id, programme_id,
rubrique (terrain/vrd/construction/frais_generaux/charges_directes),
libellé,                  -- ex: "ACHAT TERRAIN", "ENEDIS", "MOE OPC"
prestation_id,            -- lien vers référentiel prestations
code_comptable_id,
-- Colonnes bilan
montant_etude_fi,         -- prévisionnel initial
montant_marché_signé,     -- marchés signés sans avenants
montant_bilan_réel,       -- facturé réel avec avenants
commentaire,
-- Calculés automatiquement
delta_etude_signe,        -- étude - signé
delta_etude_bilan         -- étude - réel
```

**commissions** *(enrichi — taux variables par lot)*
```sql
id, prescripteur_id, lot_id, acquéreur_id,
taux_pct,                 -- taux spécifique au lot (2.5% à 5.25%)
montant_ht, tva, montant_ttc,
type_pub,                 -- ECOPUB, MADN, COBRA, HABITEO, UNLATCH...
statut (calculée/bon_émis/facture_reçue/payée),
date_déclenchement, date_paiement,
intacct_id
```

**financements_programme** *(enrichi — issu Flora)*
```sql
id, programme_id,
type (fonds_propres/credit_promo/refinancement),
partenaire,               -- ex: "Homunity" (refinancement FP)
pourcentage_qp,           -- ex: 60% pour Envol
montant_total,
montant_récupéré,
banque, numéro_ligne, montant_autorisé,
taux_interet, date_obtention, date_fin,
statut (en_attente/actif/soldé)
```

---

## Acte d'Engagement — template (issu Modèle_AE_2022.docx)

Généré automatiquement à la création d'un marché. Champs auto-remplis :

```
En-tête     : département, commune, numéro dossier, adresse terrain
Projet      : nom programme, nb étages, nb logements, nb parkings, parcelle cadastrale
Titulaire   : depuis fiche fournisseur Intacct (nom, SIRET, adresse, représentant légal)
Prix        : montant HT, TVA 20%, TTC, montant en lettres (auto)
Règlement   : 45 jours fin de mois, 90%/5%/5% RG (standard Envol)
Délai       : dates démarrage et fin saisies dans le marché
Validité    : 90 jours (fixe)
Signatures  : Maître d'ouvrage (SAS ENVOL, 1729 Avenue de la Pompignane, Montpellier)
```

---

## Documents fournis — liste mise à jour

- [x] **Liste lots/prestations** → LISTES_LOTS_ENVOL.csv ✅
- [x] **Exemple de facturation programme** → Facturation_Mauguio_Flora.xlsx ✅
- [x] **Modèle Acte d'Engagement** → Modèle_AE_2022.docx ✅
- [x] **Prototype Lovable** → facturationenvol-main.zip ✅ (logique métier + données réelles ARBORÉA + LOU MARQUES)
- [ ] Étude financière / bilan prévisionnel complet (structure postes détaillée)
- [ ] Plan comptable Sage Intacct complet
- [ ] Workflow de validation factures actuel
- [ ] Liste des rôles utilisateurs et droits précis
- [ ] Seuils de validation (montants par niveau)
- [ ] Fiche client / acquéreur actuelle (Unlatch)
- [ ] Arborescence SharePoint actuelle (capture écran)

---

## Fonctionnalités commerciales

### Offres commerciales temporaires
- Créées par la Direction uniquement
- Prix réduit sur un lot pendant une période définie
- Expiration automatique à la date de fin
- Alerte direction 3 jours avant expiration
- Si lot réservé pendant l'offre → prix offre appliqué + étude fi mise à jour
- Historique complet et non modifiable

### Prescripteurs
- Fiche prescripteur (CGP, agent immo, courtier...)
- Commission calculée automatiquement à la réservation ou à l'acte
- Bon de commission généré en PDF
- Export vers Intacct (code comptable commissions)
- Suivi des commissions par programme et par prescripteur

### TMA (Travaux Modificatifs Acquéreurs)
- Demande acquéreur liée à un lot
- Chiffrage par l'entreprise concernée (marché existant)
- Devis TMA → acceptation acquéreur
- Si accepté → avenant prix lot + OS entreprise généré
- Impact étude fi : recettes + et dépenses +

### TS (Travaux Supplémentaires)
- Distinct des TMA : travaux décidés par le conducteur, non demandés par l'acquéreur
- Lié à un lot technique et une entreprise
- Avenant au marché concerné
- Suivi facturation entreprise vs devis client

### Associés
- Tour de table par programme (% participation)
- Appels de fonds associés avec suivi des règlements
- Comptes courants d'associés
- Répartition automatique de la marge selon %
- Documents : pacte d'associés, PV AG → SharePoint

---

## Tableaux de bord et graphiques

### Dashboard direction (multi-programmes)
- Commercialisation par programme (barres)
- CA prévisionnel vs sécurisé (consolidé)
- Marge consolidée et par programme
- Factures en attente de validation
- Trésorerie prévisionnelle 12 mois (courbe)
- Alertes : documents manquants, paiements en retard, offres expirant

### Dashboard par programme (confirmé prototype)
- KPIs : Engagé Total HT / Payé à Date TTC / Reste à Payer TTC / Marge TMA TTC
- Avancement financier par lot (barres : Engagé HT vs Payé HT)
- Courbe S — avancement cumulé vs budget (lignes)
- Alertes paiements en retard (statut "Émise" sans date paiement)
- Synthèses : Taxes / Concessionnaires / Commercialisation (camembert statuts)

### Plan de trésorerie (confirmé prototype)
- Tableau glissant sur N mois (paramétrable : 6, 12, 18 mois)
- Recettes : lots actés (consolidés) + lots en stock/réservés (ligne par lot)
- Dépenses : Travaux / Prestataires / Concessionnaires / Taxes
- Solde mensuel et cumulé
- Export Excel

### Reste à Payer (confirmé prototype — 4 onglets)
- Travaux : reste HT par lot technique
- Retenues de Garantie : RG cumulée / caution / RG effective / restante
- Compte Prorata : base éligible × taux par lot (lots 01 et 02 exclus)
- Concessionnaires + Taxes

### Technologie graphiques
- **ApexCharts** intégré dans Vue.js (ou Recharts si composants partagés avec prototype)
- Export PDF du dashboard en un clic
- Données temps réel depuis PostgreSQL

---

## RGPD

### Principes
- Consentement tracé à la création de la fiche acquéreur
- Minimisation des données — pas de données inutiles
- Durée de conservation : 5 ans après acte ou abandon dossier
- Anonymisation (pas suppression) pour garder cohérence comptable
- Dossier SharePoint acquéreur : accès restreint ERP-DAF + ERP-Admin uniquement
- Logs d'accès sur toutes les fiches acquéreurs

### Droits acquéreurs
- Export de toutes ses données en PDF (depuis admin)
- Modification depuis l'ERP
- Anonymisation sur demande

### Registre des traitements (à documenter)
- Traitement : Gestion acquéreurs
- Finalité : Suivi acquisition immobilière
- Base légale : Contrat
- Durée : 5 ans après acte
- Destinataires : Notaire, banque acquéreur
- Transfert hors UE : Aucun

---

## Documents à fournir avant de coder

> ⚠️ Ces documents sont nécessaires pour que les prompts Cursor collent à votre réalité métier.
> Anonymisez les données sensibles avant envoi.

- [ ] **Étude financière / bilan prévisionnel** (Excel) — structure des postes
- [ ] **Template de budget par programme** — nomenclature des postes de dépenses
- [ ] **Exemple de situation de travaux** (Excel ou PDF)
- [ ] **Modèle d'Ordre de Service** actuel (Word ou PDF)
- [ ] **Exemple de fiche fournisseur** depuis Intacct (anonymisé)
- [ ] **Plan comptable** utilisé dans Sage Intacct
- [ ] **Codes analytiques** par type de programme
- [ ] **Workflow de validation** des factures actuel
- [ ] **Liste des rôles utilisateurs** et leurs droits précis
- [ ] **Seuils de validation** (montants par niveau)
- [ ] **Fiche client / acquéreur** actuelle (Unlatch ou Pegao)
- [ ] **Template suivi TMA** si existant
- [ ] **Arborescence SharePoint** actuelle (capture écran)
- [ ] **Liste types de marchés** (lots techniques utilisés)

---

## Numérique Responsable (RSE)

> Principe directeur : sobriété, localité, efficacité, mesure.

### Hébergement
- ✅ OVHcloud France (Roubaix / Gravelines) — hébergeur français, énergie bas carbone
- ✅ Dimensionnement serveur au plus juste — pas de surprovisionnement
- ✅ Services managés — pas de serveur inutile à faire tourner
- 🔲 Extinction automatique des environnements dev/staging la nuit (scheduler Laravel)

### Architecture
- ✅ Réutilisation de SharePoint existant — pas d'infra GED supplémentaire
- ✅ Cache Redis agressif — réduction des requêtes base de données
- ✅ Stack épurée — pas de logiciels tiers inutiles
- 🔲 Compression images et assets — réduction bande passante
- 🔲 Optimisation requêtes SQL dès le départ — moins de charge serveur

### IA responsable
- Appels API Claude uniquement quand nécessaire — pas d'appels automatiques inutiles
- Prompts courts et ciblés — moins de tokens = moins d'énergie
- Aucune donnée personnelle dans les prompts envoyés à l'API

### Outils de développement
- ✅ Cursor — tourne en local, pas de cloud permanent
- ✅ GitHub — versioning, compense ses émissions carbone
- ✅ OVHcloud — hébergeur français engagé

### Mesure (à implémenter)
- Dashboard RSE numérique interne :
  - Consommation estimée OVHcloud
  - Nombre d'appels API Claude / mois
  - Taux de cache Redis (requêtes évitées)
  - Uptime et efficacité serveur

---

## Intégration Signature Électronique — Yousign

- **Solution retenue** : Yousign (🇫🇷 français, conforme eIDAS, RGPD)
- **Usage** : signature des contrats de réservation VEFA par les acquéreurs
- **Déclenchement** : automatique à la création de la réservation

### Workflow

```
Réservation créée dans l'ERP
        ↓
Génération automatique du contrat VEFA (PDF)
        ↓
Envoi via API Yousign → email à l'acquéreur
        ↓
Acquéreur signe en ligne (mobile ou desktop)
        ↓
Webhook Yousign → ERP mis à jour automatiquement
        ↓
Document signé stocké sur SharePoint
```

### Points clés
- API REST bien documentée
- Webhooks pour mise à jour statut en temps réel
- Document signé archivé automatiquement sur SharePoint via Graph API

---

## Intégration AR24 — Purge délai de rétractation SRU

- **Solution retenue** : AR24 (Lettre Recommandée Électronique à valeur légale)
- **Alternative possible** : Maileva (La Poste) — valeur légale incontestable
- **Usage** : notification SRU acquéreur → déclenche le délai de rétractation 10 jours

### Workflow

```
Contrat VEFA signé (Yousign)
        ↓
ERP génère la lettre de notification SRU
        ↓
Envoi via API AR24 (LRE avec accusé de réception)
        ↓
Webhook AR24 → statut mis à jour dans l'ERP
        ↓
Délai 10 jours déclenché automatiquement
        ↓
Alerte automatique à J+10 → lot passé en "vendu confirmé"
```

### Points clés
- Accusé de réception horodaté = preuve légale
- Comptage automatique des 10 jours dans l'ERP
- Alerte direction si délai dépassé sans confirmation

---

## GED — Gestion documentaire via SharePoint

### Principe
- Documents stockés **uniquement sur SharePoint** — pas de doublon
- L'ERP pointe vers les fichiers via leur URL SharePoint
- Upload toujours via l'ERP → classement automatique dans le bon dossier SharePoint

### Arborescence SharePoint (créée automatiquement à la création d'un programme)
```
SharePoint / Sites / ERP-Immo / Programmes
└── PRG-2024-001 — Résidence Les Pins
    ├── 01-Foncier (Actes, Promesses, Études)
    ├── 02-Administratif (PC, DO, DAACT, Assurances)
    ├── 03-Marchés
    │   └── MCH-001 — Gros œuvre
    │       ├── Marché signé
    │       └── Factures
    ├── 04-Finance
    └── 05-Livraison
```

### Types de documents (classification à l'upload)
Acte d'achat, Promesse de vente, Permis de construire, DO, DAACT, Assurance DO, Marché signé, Avenant, Facture, Situation de travaux, PV de réception, Autre

### Checklist documentaire par programme
```
✅ Acte d'achat          12/03/2024   [Ouvrir]
✅ Permis de construire  05/06/2024   [Ouvrir]
⏳ DO                    manquant     [Uploader]
⏳ Assurance DO          manquant     [Uploader]
```

### Synchro depuis SharePoint
- Toutes les 10 minutes via Graph API
- Fichiers uploadés directement dans SharePoint apparaissent dans l'ERP
- Classement automatique basé sur la position dans l'arborescence

---

## Gestion des droits — Groupes de sécurité M365

- **Identité et appartenance aux groupes** : Microsoft Entra ID (source de vérité)
- Groupes lus via Microsoft Graph API à la connexion → mis en cache Redis
- **Droits fins par fonctionnalité** : système ERP `features_permissions` au-dessus des groupes M365 (voir section "Système de droits par fonctionnalité")

### Groupes M365 à créer
```
ERP-Admin        → accès total, administration
ERP-DAF          → finance, bilan, validation factures niveau 2
ERP-Conducteur   → marchés, factures, chantier, validation niveau 1
ERP-Direction    → lecture globale + validation finale (si > seuil)
ERP-Lecture      → tableaux de bord uniquement
```

---

## Intégration Sage Intacct

- **Type d'API** : XML over HTTPS (pas REST classique)
- **Fournisseurs** : viennent exclusivement de Sage Intacct — aucune création dans l'ERP
- **Synchronisation** : par lot (jobs Laravel + Redis)

### Jobs de synchronisation

| Job | Sens | Fréquence |
|---|---|---|
| SyncFournisseursDepuisIntacct | Intacct → ERP | 1x/nuit à 2h + bouton admin |
| SyncProgrammesVersIntacct | ERP → Intacct | 1x/nuit à 3h |
| EnvoyerFacturesValidees | ERP → Intacct | Toutes les 2h |
| RecupererPaiementsIntacct | Intacct → ERP | Toutes les 2h |

### Bouton admin "Synchroniser maintenant"
- Disponible pour chaque job sur la page admin
- Affiche le résultat immédiatement ("247 fournisseurs importés")

### Champs de synchro
```sql
intacct_id, intacct_synced_at, intacct_error
```

### Gestion des erreurs
- 3 tentatives avec backoff exponentiel (1min, 5min, 15min)
- Dashboard monitoring : statut, erreurs, dernière exécution

### IA sur les factures
- Extraction automatique via API Claude : numéro, montant HT, TVA, TTC, date, fournisseur, référence marché
- Détection d'anomalies : facture > marché, doublon, TVA incorrecte

---

## Workflow de validation des factures

### Étapes complètes

```
Facture reçue (upload ERP ou import Intacct)
        ↓
Détection automatique du type → assignation validateur NV1
        ↓
NV1 — Conducteur / Commercial / Juriste
(selon type de facture, paramétrable en admin)
        ↓
NV2 — PDG (toutes les factures sans exception)
        ↓
Mise en paiement — Comptable
(prépare dans Intacct → export)
        ↓
Exécution virement — DAF
(dans la suite bancaire, hors ERP)
        ↓
Confirmation paiement effectif
(Intacct → ERP automatique)
        ↓
Bilan mis à jour + notification
```

### Validateur NV1 selon type de facture (paramétrable admin)

| Type de facture | Validateur NV1 |
|---|---|
| Situation de travaux | Conducteur de travaux |
| Honoraires MOE / BET / OPC | Conducteur de travaux |
| Frais commerciaux / prescripteurs | Responsable commercial |
| Frais juridiques / notaire | Juriste |
| Autres | Responsable programme |

### Notifications automatiques

| Événement | Notifié |
|---|---|
| Facture reçue | Validateur NV1 concerné |
| NV1 validé | PDG |
| PDG validé | Comptable |
| Mise en paiement Intacct | DAF (+ lien suite bancaire) |
| Paiement effectif confirmé | Conducteur + Responsable financier |

### Gestion des délais et relances
- NV1 non traité après 48h → relance automatique
- NV1 non traité après 72h → alerte Responsable programme
- PDG non traité après 48h → relance automatique

### Tables workflow
```sql
-- types_factures
id, libellé, validateur_nv1_role, code_comptable_défaut

-- workflow_validations
id, facture_id,
niveau (nv1/nv2/mise_paiement/paiement_effectif),
validateur_id, statut (en_attente/validé/rejeté/relancé),
date_assignation, date_validation,
commentaire, relances_count
```

### Tableau de bord comptable
```
💳 PAIEMENTS EN COURS
─────────────────────────────────────
À préparer (PDG validé)     : 4 factures   89 200€
Préparés (en attente DAF)   : 3 factures  125 400€
Exécutés ce mois            : 12 factures 380 000€
```

---

## Responsables par programme

### Rôles définis par programme
```
👤 Responsable programme      → pilote global
👤 Responsable commercial     → ventes, prescripteurs, offres
👤 Responsable suivi client   → acquéreurs, TMA, livraison
👤 Conducteur de travaux      → marchés, factures, chantier
👤 Responsable financier      → bilan, validation financière
```

Un utilisateur peut avoir des rôles différents selon les programmes.

### Table programme_responsables
```sql
id, programme_id, user_id,
rôle (responsable_programme/commercial/
      suivi_client/conducteur_travaux/responsable_financier),
date_début, date_fin
```

---

## Code analytique programme

### Format retenu
```
PRG - {département} - {code_projet}
ex: PRG-75-LESPINS
    PRG-69-BELLECOUR
    PRG-13-CASTEL
```

### Règles
- Département : liste déroulante 01-976
- Code projet : lettres/chiffres uniquement, max 10 caractères, majuscules
- Unicité garantie — impossible de créer deux programmes avec le même code
- **Non modifiable après création** — cohérence avec Intacct
- Généré à la création du programme → envoyé vers Intacct automatiquement
- Comptables utilisent ce code dans Intacct pour toutes les factures du programme

---

## Factures — Import depuis Intacct

### Principe de filtrage
- L'ERP génère le code analytique PRG-xx-xxxx
- Les comptables l'utilisent dans Intacct sur les factures de programme
- L'ERP n'importe **que** les factures avec un code analytique PRG-xx-xxxx
- Les factures générales (sans code PRG) restent dans Intacct uniquement

### Job d'import
```
RecupererFacturesDepuisIntacct (toutes les 2h)
        ↓
Factures Intacct avec code analytique PRG-xx-xxxx
non encore importées
        ↓
Import dans l'ERP + association programme
        ↓
Association automatique au marché
(si un seul marché actif pour ce fournisseur)
ou proposition manuelle (si plusieurs marchés)
        ↓
Déclenchement workflow validation NV1
```

### Champs supplémentaires sur factures
```sql
source (erp_upload/intacct_import/facturx_intacct),
intacct_bill_id,
code_analytique,
association_auto (booléen)
```

---

## Factur-X

- Obligatoire progressivement : réception 2026, émission 2027-2028
- Sage Intacct gère la plateforme d'agrément → l'ERP ne gère pas la transmission
- **Réception** : factures Factur-X reçues via Intacct → données XML extraites automatiquement → pas d'OCR nécessaire
- **Émission** : appels de fonds générés dans l'ERP → envoyés vers Intacct → Intacct transmet à la plateforme
- Bibliothèque PHP : `atgp/facturx` intégrée dans Laravel

---

## MVP — Sprints prioritaires

### Sprint 1 — Fondations (2-3 jours)
- Auth SSO Microsoft + groupes de sécurité M365
- Gestion des rôles globaux (Admin / DAF / Conducteur / Direction / Lecture)
- Structure de base : sociétés, programmes + code analytique PRG-xx-xxxx
- Responsables par programme (conducteur, commercial, juriste, financier...)
- Synchro fournisseurs Intacct (prérequis pour les marchés)
- Bouton admin "Synchroniser fournisseurs maintenant"
- Création automatique arborescence SharePoint à la création d'un programme

### Sprint 2 — Bilan financier prévisionnel (3-4 jours)
- Création budget par programme (postes de dépenses + codes comptables)
- Import depuis fichiers Excel existants
- Gestion comptes bancaires par programme (fonds propres / ligne de crédit)
- Tableau de bord financier en temps réel
- Mise à jour automatique quand marchés / factures ajoutés

### Sprint 3 — Marchés & Suivi chantier (2-3 jours)
- Création marché depuis devis fournisseur Intacct
- Génération automatique OS en PDF
- Avenants
- Situations de travaux (avec RG et compte prorata — logique validée dans le prototype)
- TS (Travaux Supplémentaires)
- Mise à jour automatique du bilan
- Upload marché signé → SharePoint (dossier automatique)
- Vue "Reste à Payer" (travaux + RG + compte prorata + concessionnaires + taxes)
- Plan de trésorerie glissant

### Sprint 4 — Factures (3-4 jours)
- Upload facture PDF depuis l'ERP + OCR via Claude API
- Import automatique depuis Intacct (filtre code analytique PRG)
- Association au marché (auto ou manuelle)
- Workflow complet : NV1 (selon type) → PDG → Comptable → DAF → Paiement
- Notifications à chaque étape + relances automatiques
- Stockage automatique dans SharePoint

### Sprint 5 — Intacct + Paiement (2 jours)
- Export facture validée vers Sage Intacct
- Récupération paiement effectif depuis Intacct
- Mise à jour bilan en temps réel
- Notification DAF avec lien suite bancaire
- Notification confirmation paiement

---

## Décisions techniques prises

- ✅ Pas de GED custom → on s'appuie sur SharePoint existant
- ✅ Hébergement français → OVHcloud Public Cloud (France)
- ✅ Stack épurée → OVHcloud + GitHub + Cursor uniquement
- ✅ Auth SSO → Microsoft Entra ID
- ✅ Frontend → Vue.js 3 + Inertia.js
- ✅ IA → API Claude pour extraction factures PDF + détection anomalies
- ✅ Comptabilité → Sage Intacct synchronisé par lots (jobs Redis)
- ✅ Workflow factures → NV1 (selon type) → PDG → Comptable → DAF (suite bancaire)
- ✅ Code analytique → PRG-{département}-{code} généré par l'ERP, source de vérité
- ✅ Import factures Intacct → filtre code analytique PRG uniquement
- ✅ Factur-X → géré par Intacct + plateforme agrément existante
- ✅ Responsables par programme → rôles définis programme par programme
- ✅ Signature électronique → Yousign — phase 2
- ✅ Purge SRU → AR24 — phase 2
- ✅ Portabilité totale → stack open source, export natif, changement hébergeur en quelques heures
- ✅ Prototype Lovable → utilisé comme source de vérité pour la logique métier (calculs, modèle de données, UX) et fixtures de test (données ARBORÉA + LOU MARQUES)

---

## Environnement existant

- **Microsoft 365** : utilisé par toute l'équipe
- **SharePoint** : documents de programmes déjà organisés dessus
- **Pegao** : ERP actuel (2 400€/mois), utilisé pour tous les modules → à remplacer progressivement
- **Unlatch** : outil commercial actuel (CRM vente, signature eIDAS, recommandé électronique, portail acquéreur) → à remplacer en phase 2 par Yousign + AR24 intégrés dans l'ERP

---

## Avancement réel de l'ERP (mise à jour mai 2026)

> Le projet est largement plus avancé que la roadmap initiale prévoyait. L'ERP est en production sur https://envol.hectare.fr (OVH cluster113), accessible aux utilisateurs M365 du groupe Hectare.

### Stack réelle déployée
- **Backend** : Laravel 13 / PHP 8.3
- **Base de données** : MySQL OVH (pas PostgreSQL initialement prévu)
- **Frontend** : Vue 3 + Inertia + PrimeVue + Tailwind
- **Hébergement** : OVH mutualisé cluster113 (pas Public Cloud)
- **Queue** : `QUEUE_CONNECTION=sync` (pas de worker Redis)
- **Auth** : SSO M365 via Laravel Socialite + Microsoft Graph
- **Build front** : `npm run build` en local, `public/build/` poussé dans git avec `git add -f`
- **Vendor** : committé dans le repo
- **Composer** : pas global sur OVH, mais `composer.phar` disponible (`php composer.phar dump-autoload -o`)
- **Repo** : HECTAREG/erp-immo (GitHub privé)

### Groupes M365 utilisés
- `GS_ADMIN_ERP` — administration
- `GS_COMPTABILITE` — finance/factures
- `GS_DIRECTION_GENERALE` — direction
- `GS_DSI` — DSI
- `GS_ENVOL` — utilisateurs Envol

### Modules en production
- ✅ **Auth SSO M365** + groupes
- ✅ **Annuaire** (utilisateurs, fournisseurs Intacct)
- ✅ **Programmes** + code analytique PRG-{dpt}-{code}
- ✅ **Suivi Chantier** : marchés, avenants, situations (modèle issu prototype Lovable)
- ✅ **Bilan financier** prévisionnel
- ✅ **Factures** : workflow validation NV1/NV2/compta + dépôt + association marchés
- ✅ **Synchro Sage Intacct** : fournisseurs, factures
- ✅ **Devis multi-versions** par indice AAAAMMJJ
- ✅ **Appels d'Offres V1** : DCE.zip + Estimatif MOE.pdf via AoDocumentService
- ✅ **Module Capture Leads Meta Ads** (livré mai 2026 — voir section dédiée)
- ✅ **Système de droits par fonctionnalité** (livré 24 mai 2026 — features_permissions + UI /admin/droits)
- ✅ **Dashboard widgets personnalisables** (livré 24 mai 2026 — 10 widgets, drag & drop, layout par user)
- ✅ **Refonte page /admin** (livré 24 mai 2026 — onglets par catégorie, header avec toggle emails + synchro Intacct)
- ✅ **Refonte UX Service client** (livré 25 mai 2026, commit `44dde03` — TMA + AdF regroupés en page conteneur)
- ✅ **Liaison Stades VEFA ↔ Chronologie** (livré 25 mai 2026, commit `23b9252`)
- ✅ **Module Bibliothèque TMA** (livré 25 mai 2026, commit `641c2f7` — catalogue global + overrides programme) + hotfix `11cfac5`
- 🚧 **Switch programme depuis breadcrumb** (livré 25 mai 2026, commit `4284193` — **BUG Ziggy en prod, fix en cours**)
- ✅ **Refonte Factures en sous-onglet de Suivi Chantier** (livré 25 mai 2026, commit `6981623`)
- ✅ **Tooling Meta — replay + health check** (livré 26 mai 2026, commits `61d1b0e`, `2d753de`, `cb14a70`+) — 27 leads rejoués sur l'incident 23-26/05
- 🚧 **Refonte comptabilisation Intacct** (livré 26 mai 2026 — `ExtBillCreate` + SDK custom + endpoint debug — **bug résiduel `UPDATE_REFERENCE_NUMBER`**)
- 🚧 **Module Appels de Fonds VEFA** (Sprints 1-6 déployés en prod 23/05/2026 — pas encore testés en prod, logo/pattern PNG à uploader)

### Modules à venir (roadmap restante)
- 🔲 Module CIE (cahier des charges prêt)
- 🔲 Module Juridique/Contentieux
- 🔲 Plan trésorerie
- 🔲 ARINVOICE Intacct (lié appels de fonds)
- 🔲 Prescripteurs + commissions
- 🔲 Portail acquéreur extranet (branding AVRA/MIRA/ALYA/NOOS)
- 🔲 Multi-tenant Meta leads (4 sociétés HECTARE/Envol/Gemme/Les Balcons de la Cité)

---

## Module Capture Leads Meta Ads (livré mai 2026)

### Architecture
```
Meta (formulaire Lead Ads)
  → Webhook POST /api/webhooks/meta/leadgen
  → MetaWebhookController (vérif HMAC avec META_APP_SECRET)
  → Job ProcessMetaLead (idempotence sur meta_lead_id)
  → MetaGraphService::getLead() + getCampaign() via Marketing API
  → MetaLeadIngestionService (résolution programme + commercial)
    1. Lookup meta_campaign_id dans meta_campaign_codes (clé principale)
    2. Fallback regex code 3 chiffres /^(\d{3})\s*-/
    3. Si commercial null → LEADS_FALLBACK_COMMERCIAL_USER_ID
  → Persistance leads_marketing (BDD)
  → Job CreateLeadSharePointItem (3 retries, backoff 60/300/900s)
  → Job NotifyCommercialTeams (email HTML enrichi via Graph Mail.Send applicatif)
```

### Configuration Meta côté Hectare (app GESTION_PROSPECT)
- App ID : `2827608434238325`
- Page abonnée : Hectare-Aménageur (`570810992938193`)
- Webhook v22, événement `leadgen`
- Permissions accordées : ads_read, ads_management, leads_retrieval, pages_show_list, pages_read_engagement, pages_manage_metadata, pages_manage_ads, business_management
- App publiée (mode dev → prod), URL confidentialité renseignée

### Variables .env clés
```
META_APP_ID=2827608434238325
META_APP_SECRET=...
META_PAGE_ACCESS_TOKEN=...    # Token Page Hectare-Aménageur
META_PAGE_ID=570810992938193
META_AD_ACCOUNT_ID=act_1193405381139978
META_WEBHOOK_VERIFY_TOKEN=...
META_GRAPH_API_VERSION=v22.0
META_VERIFY_SSL=true           # false en local MAMP
LEADS_FALLBACK_COMMERCIAL_USER_ID=1
LEADS_FALLBACK_EMAIL=aurelie.portales@hectare.fr
LEADS_SHAREPOINT_SITE_ID=b8893f4d-eec8-4f58-8ee1-3a10b6295ac3
LEADS_SHAREPOINT_LIST_ID=5a66d8c2-e4d6-419c-ae2a-38deaf25b34f
AZURE_MAIL_EXPEDITEUR=hectarion@hectaregroupe.fr
```

### SharePoint liste PROSPECTS-FACEBOOK
Site CENTRE-DE-RESSOURCES. Colonnes créées par import CSV → noms internes génériques `field_1` à `field_11`. Mapping centralisé dans `config/leads_marketing.php` :

| Field | Type SP | Contenu |
|---|---|---|
| Title | Texte | "Prénom Nom" |
| field_1 | Texte | Email |
| field_2 | Texte | Téléphone |
| field_3 | Texte | Programme |
| field_4 | Texte | Code campagne |
| field_5 | Texte | Nom campagne |
| field_6 | Texte | Commercial Référent ("Nom (email)") |
| field_7 | **Date/Heure** | Date de réception (format ISO Europe/Paris) |
| field_8 | **Choix** | Statut (Nouveau/Contacté/Qualifié/RDV/Réservation/Perdu) |
| field_9 | **Plusieurs lignes** | Champs supplémentaires Meta (texte multiligne) |
| field_10 | Texte | URL ERP |
| field_11 | Texte | ID Lead Meta |

**Pièges identifiés et résolus** :
- field_9 doit être "Plusieurs lignes de texte" pour accepter retours ligne (sinon 400 Invalid request)
- field_6 utilise parenthèses `Nom (email)` pas chevrons `<>` (sinon SP interprète comme HTML)
- field_10 reste texte simple (pas Hyperlink — pose problème)
- Clés JSON dans field_9 normalisées : `\W → _`, minuscules, max 80 char
- Valeurs sanitizées : `strip_tags()` + retrait caractères de contrôle
- Apostrophes typographiques `’` causent souci sur champ Texte 1 ligne → solution : multiligne

### UI Admin livrée
- `/admin/leads-marketing` — Liste filtres recherche (clic ligne → détail)
- `/admin/leads-marketing/{id}` — Détail, statut éditable inline, commercial éditable inline, bouton "Relancer SharePoint" et "Renvoyer notification" TOUJOURS visibles
- `/admin/marketing/codes-campagnes` — CRUD inline commercial, import Meta depuis campagnes actives
- `/admin/marketing/codes-campagnes/import-meta` — Tableau campagnes actives Meta, code optionnel, commercial optionnel, bulk create
- `/admin/sp/test-fields` — Debug GS_DSI : séquence cumulative avec payload réel du lead 2
- Cartes admin : "Prospects marketing" et "Codes campagnes marketing"
- **Lien "Prospects" retiré du menu nav principal** (accès via /admin uniquement)

### M365CommercialUserResolver
Provisioning automatique d'utilisateurs M365 dans l'ERP même s'ils ne se sont jamais connectés :
- Recherche par `azure_id` ou email
- Si absent : création `users` avec `name` (displayName Graph), `email`, `azure_id`, mot de passe aléatoire inutilisable, `email_verified_at` + `preapproved_at`
- Utilisé pour codes campagnes ET édition inline commercial fiche lead
- Migration `users.preapproved_at` à exécuter

### Notification email enrichie
- **TO** : commercial du lead (commercial_user.email)
- **CC fixe** : aurelie.portales@hectare.fr + hectarion@hectaregroupe.fr
- **Fallback** : si commercial null → TO = aurelie.portales@hectare.fr
- **Sujet** : "🔥 Nouveau prospect à contacter — {campagne} — {prenom} {nom}"
- **Contenu HTML** : ouverture incitative ("contacter dans les 5 minutes"), tableau coordonnées, infos formulaire Meta humanisées, CTA bouton "Voir tous les prospects sur SharePoint", footer sobre
- **Canal** : Microsoft Graph Mail.Send Application (HTTP 200/202/204 acceptés)
- **Mention** : le mail ne va JAMAIS au client, uniquement au commercial Hectare

### Configuration Azure Mail.Send
- Mail.Send doit être en **Application** (pas Déléguée) avec consentement admin accordé
- L'app peut alors envoyer depuis n'importe quelle boîte du tenant (hectarion, robin...) si pas d'Application Access Policy restrictive

### Helper emailsEnabled()
`app/Helpers/SettingHelper.php` définit `emailsEnabled()` qui lit le setting `emails_enabled`. Doit être listé dans `composer.json` → `autoload.files` puis `php composer.phar dump-autoload -o` pour être chargé. Sinon : `Call to undefined function emailsEnabled()`.

---

## Audit emails (état mai 2026)

### Politique : 2 envois ACTIFS, le reste DÉSACTIVÉ

**Actifs :**
1. **Leads marketing (Meta)** — NotifyCommercialTeams
   - TO : commercial_user.email | Fallback : `config('leads_marketing.fallback_email')` → `aurelie.portales@hectare.fr`
   - CC : aurelie + hectarion
   - Canal : Graph applicatif
2. **Demandes fournisseurs** — DemandeFournisseurController::envoyerEmailComptabilite
   - TO : `config('notifications.fournisseurs_email')` → `comptabilite@hectare.fr` (fixe)
   - Canal : Graph applicatif (nouveau)
   - Notification cloche GS_COMPTABILITE conservée

**Désactivés** (`Log::info('Email désactivé pour [...]')`) :
- Validations facture NV1/NV2/compta — `NotificationFactureService` (assignation validateur_id conservée)
- Relances factures — `NotificationFactureService::relancerValidateur` (plus d'incrément relances_count)
- Réservations acquéreur 4 alertes ODF/accord/SRU/documents — `AlerteService` (alertes cloche conservées)
- Devis TMA client — `TMAController` (statut "Envoyé" conservé)
- Alertes SharePoint AO/devis — Jobs `UploadDevisToSharePoint` / `UploadAoDocumentToSharePoint`

Documenté dans `docs/audit-emails.md`.

---

## Module Appels de Fonds VEFA (déployé prod 23/05/2026, en rodage)

### Spécifications validées avec DSI

**Stades d'avancement** :
- Modèle par défaut : 25% Fondations / 50% Élévation / 75% Hors d'eau / 95% Cloisons / 100% Livraison
- Paramétrables par programme (libellés et % modifiables)

**Génération** :
- Bouton manuel par stade depuis fiche programme
- Déclenche traitement batch tous acquéreurs ACTÉS du programme
- Pas d'envoi automatique au client en phase 1 (bouton manuel "Envoyer à l'acquéreur" — rodage)

**Document** :
- PDF généré + dépôt SharePoint dossier acquéreur
- Format = appel de fonds = facture client (un seul document pour les 2 usages)
- Template charte Envol : pattern hexagonal haut, logo, filet rose séparateur, bandeau rose bas, couleurs `#ebbab8` + `#3c3c3b`

**Intacct** :
- Création AR Invoice (facture CLIENT) via Sage API existante
- Acquéreurs créés dans Intacct au moment de la 1ère AdF (lazy, sans doublon)
- Code analytique programme PRG-{dpt}-{code} reporté
- Référence externe (n° AdF) pour rapprochement automatique
- TVA 20% (bâtiment neuf libre)

**Numérotation** : `AF-{code_societe}-{annee}-{seq}` (ex: `AF-023-2026-014`)
- Code société = 3 chiffres défini par programme (ex: E023 → 023)

**Échéance** : point de départ = date de génération de l'appel de fonds

**Suivi paiements / relances** :
- Dashboard "AdF en retard" sans automatisation
- Bouton manuel "Relancer" génère email
- Pas d'automation pour éviter relances erronées (Intacct peut être en retard sur les encaissements)

**TMA** : facture SÉPARÉE, PAS dans appels de fonds

### Coordonnées société par programme (à saisir)
Ajoutées à la table `programmes` :
- raison_sociale (ex: ENVOL SAS)
- adresse complète
- siret, rcs, capital_social, tva_intracom
- iban, bic, banque, référence compte

### Logo Envol officiel (charte 2019)
- Couleurs : Rose Envol `#ebbab8` + Gris foncé `#3c3c3b`
- Typo : ITC Avant Garde Gothic Extra Light (titres) + Book (corps) — fallback web Montserrat
- Logo officiel : `/mnt/user-data/uploads/LOGO_ENVOL.pdf` (à intégrer en PNG/PDF dans les générations)
- Pattern hexagonal : `/mnt/user-data/uploads/A4___Pattern_Envol.pdf`
- Adresse société Envol : 1729 Avenue de la Pompignane, 34000 MONTPELLIER, 04 67 79 84 83, www.envol.fr

### Mockup validé
Design HTML validé en session — éléments visuels :
- Pattern hexagonal en haut (opacité 50%)
- Logo centré (placeholder — Cursor utilisera vrai PDF)
- Filet rose séparateur
- 2 colonnes : Programme (nom commercial ERP) | Acquéreur
- Titre "APPEL DE FONDS" en typo fine + n° AF-023-2026-014 + date
- 3 encarts rose pâle : Lot / Référence dossier / Échéance
- Barre d'avancement 5 stades (% atteints en rose, à venir en rose pâle)
- Mention légale R261-14 CCH
- Tableau financier (prix acte / cumul appelé / présent appel / cumul après / reste)
- Encart rose IBAN/BIC/Référence
- Pied de page sobre + bandeau rose `#ebbab8` en bas

### Sprints 1-6 — déployés en prod le 23 mai 2026

> Module déployé en production, **pas encore testé en conditions réelles**. Logo + pattern PNG à uploader pour la génération propre des PDF.

**Sprint 1 — Coordonnées société & bancaires**
- Migration `programmes` enrichie : `code_societe` (3 chiffres), `raison_sociale`, `adresse_societe`, `siret`, `rcs`, `capital_social`, `tva_intracom`, `iban`, `bic`
- UI : onglet "Coordonnées société & bancaires" dans la fiche programme
- Droits : `GS_ADMIN_ERP` + `GS_DIRECTION_GENERALE`
- Validation IBAN : 24-34 caractères alphanumériques

**Sprint 2 — Stades d'avancement VEFA**
- Table `stades_avancement` (par programme)
- Seeder `StadesAvancementDefaultSeeder` : 25 / 50 / 75 / 95 / 100
- UI `/programmes/{id}/stades-avancement` : drag & drop, % modifiables
- Validation somme = 100%
- Droits : `GS_ADMIN_ERP` ou `responsable_programme`

**Sprint 3 — Génération AdF**
- Table `appels_de_fonds` (distincte de l'ancienne `appels_fonds` liée à la chronologie)
- Service `GenerationAppelFondService::genererBatch()`
- `NumeroAppelFondGenerator` avec verrou DB — format `AF-{code}-{annee}-{seq}`
- Échéance configurable : `APPELS_FONDS_NB_JOURS_ECHEANCE` (défaut 30)
- Idempotence sur le couple lot / stade

**Sprint 4 — PDF charte Envol**
- Service `GenerationAppelFondPDFService` + template `appel-de-fonds.blade.php`
- Stockage : `storage/app/appels-de-fonds/{programme_id}/{numero}.pdf`
- Logo + pattern à uploader dans `resources/assets/`

**Sprint 5 — Intacct (workflow révisé)**
- Numérotation à deux niveaux :
  - ERP génère `numero_interne` (`AF-XXX`)
  - Intacct attribue `numero_facture` (`FAC-XXX`)
- Workflow asynchrone : création AdF en `brouillon` → Job `CreateIntacctClientInvoice` → `en_attente_intacct` → `emis` (avec `FAC-XXX`)
- Lookup / création client Intacct par email + nom (lazy, sans doublon)
- Compte produit configurable : `APPELS_FONDS_COMPTE_PRODUIT` (défaut 706000)
- `CLASSID` = `code_analytique` du programme
- 3 retries 60 / 300 / 900s, retour à `brouillon` si échec
- Dashboard `/admin/appels-de-fonds/erreurs-intacct`

**Sprint 6 — UI + désactivation envoi acquéreur**
- UI `/programmes/{id}/appels-de-fonds` : génération batch + suivi
- Polling 10s tant que des AdF sont en `brouillon` ou `en_attente_intacct`
- Modale de confirmation de génération avec preview des lots concernés
- Bouton "Envoyer à l'acquéreur" **désactivé** via config `APPELS_FONDS_ENVOI_ACQUEREUR=false` en phase rodage
- Backend protégé : retour 403 si appelé en API avec config à `false`

### Décisions complémentaires AdF
- **PDF** : génération uniquement après obtention du `numero_facture` Intacct
- **Statuts AdF révisés** : `brouillon`, `en_attente_intacct`, `emis`, `envoye_acquereur`, `paye`, `annule`
- **Acompte à l'acte** : à valider avec compta (montant 1500€ ? déduction du 1er AdF ?) — fonctionnalité à ajouter ultérieurement

### Reste à faire post-déploiement
- Tests en prod du module Appels de Fonds (Sprints 1-6)
- Upload du logo + pattern PNG dans `resources/assets/`
- Validation acompte à l'acte avec compta

---

## Décisions techniques additionnelles (mai 2026)

- ✅ Module Meta leads : architecture webhook + jobs + idempotence sur meta_lead_id
- ✅ Notification email leads : Graph Application avec CC fixe + contenu HTML enrichi
- ✅ Politique emails : 2 cas actifs (leads + fournisseurs), le reste désactivé
- ✅ Provisioning auto users M365 (preapproved) — pas besoin de login préalable
- ✅ Édition inline commercial sur fiche lead et codes campagnes
- ✅ SharePoint date/heure : ISO Europe/Paris (pas UTC, sinon décalage -2h sur SP)
- ✅ Appels de fonds : appel = facture client (un seul document pour Intacct + acquéreur)
- ✅ Numérotation AdF : AF-{code_societe}-{annee}-{seq} (code 3 chiffres défini par programme)
- ✅ Stades VEFA : 25/50/75/95/100 par défaut, paramétrable par programme
- ✅ Numérotation AdF à deux niveaux : `numero_interne` ERP (AF-XXX) + `numero_facture` Intacct (FAC-XXX)
- ✅ Workflow AdF asynchrone : brouillon → en_attente_intacct → emis → envoye_acquereur → paye
- ✅ PDF AdF généré uniquement après obtention du numéro Intacct
- ✅ Envoi acquéreur désactivé en phase rodage (config `APPELS_FONDS_ENVOI_ACQUEREUR=false`)
- ✅ Acompte à l'acte : reporté à plus tard (à valider avec compta)
- ✅ Système de droits par fonctionnalité : couche fine au-dessus des groupes M365 (pas de refacto immédiate du code existant, migration progressive)
- ✅ Dashboard : layout personnalisable par utilisateur, widgets filtrés par permissions, cache file 5 min par widget
- ✅ Service client : page conteneur regroupant TMA + AdF, sous-onglets avec deep-link `#tma` / `#appels-fonds`, redirection 301 pour les anciennes URLs
- ✅ Stades VEFA ↔ Chronologie : FK informationnelle uniquement, la génération AdF reste pilotée par `stade_avancement_id`
- ✅ Bibliothèque TMA : catalogue global + overrides par programme (% signés avant/après coulage) + lignes snapshotées par TMA
- ✅ Coefficient prix client TMA par défaut : ×1.8 (= 1.2 × 1.5), modifiable manuellement
- ✅ `tmas.marche_id` devient nullable et non utilisé pour le pricing (multi-entreprises par ligne reporté)
- ✅ Workflow facturation TMA : même pattern asynchrone que les AdF VEFA (TMA-XXX ERP + FAC-XXX Sage)
- ✅ `public/build` **retiré du `.gitignore`** : le build front est désormais committé (cohérent avec `vendor/` committé), évite les déploiements incohérents
- ✅ **Ziggy non installé** : URLs directes obligatoires côté Vue, jamais `route()` (voir Conventions front en début de fichier)
- ✅ Switch programme : substitution regex du segment `/programmes/{id}/`, conserve query + hash, fallback dashboard programme
- ✅ Lots éligibles TMA : statuts `reserve` + `acte`
- ✅ Sous-onglets Suivi Chantier : navigation par hash (`#appels-offres`, `#marches`, `#factures`, `#cie`), compat ascendante `?tab=` via `history.replaceState`
- ✅ **Claude Code** adopté en complément de Cursor pour les sessions debug intensives (repo + shell direct, moins d'allers-retours)
- ✅ **Pattern artisan ↔ endpoint admin** : toute commande artisan qui appelle une API externe doit avoir un endpoint admin équivalent, car OVH bloque les sorties HTTPS depuis CLI/SSH
- ✅ Intacct : passage de `BillCreate` à **`ExtBillCreate`** (SDK natif), retrait des `setBaseCurrency` / `setTransactionCurrency` qui déclenchaient des erreurs
- ✅ Intacct : **SDK custom restauré dans `vendor/intacct`** (cohérent avec `vendor/` committé)
- ✅ Lecture APBILL : **fallback `query` + `readByQuery`** plus robuste que la lecture directe par ID
- ✅ Endpoint debug `/admin/intacct/test-bill` : envoi APBILL configurable champ par champ pour isoler les erreurs Intacct
- ✅ Health check Meta horaire + widget dashboard + bannière globale (détection précoce des coupures webhook)

---

## Système de droits par fonctionnalité (livré 24 mai 2026)

> Couche fine de permissions au-dessus des groupes M365. Les groupes Entra ID restent la source d'identité ; les permissions ciblent la fonctionnalité (lecture / écriture par module).

### Architecture
- Tables : `features_permissions`, `feature_permission_groups`, `audit_log_permissions`
- Catalogue : ~80 permissions (lecture / écriture par fonctionnalité)
- Mapping groupes M365 ↔ permissions (table de jointure)
- `PermissionService` avec cache 5 min (résolution par user)
- Helper global `userCan('feature.action')` côté Blade
- Composable `useUserCan` côté Vue
- Middleware `feature.permission` pour protection de routes
- Audit log de toutes les modifications de permissions

### Catégories du catalogue
- Suivi chantier
- Factures
- Bilan
- Programmes
- Commercial
- Marketing
- Appels d'offres
- Documents
- Annuaire
- Intacct
- Administration

### UI Admin `/admin/droits`
- Onglets par catégorie
- Multi-select des groupes M365 par permission
- Recherche dans le catalogue
- Filtre par groupe M365
- Audit trail des modifications

### Mapping par défaut
- `GS_DSI` : tout
- `GS_ADMIN_ERP` : quasi-tout
- `GS_DIRECTION_GENERALE`, `GS_COMPTABILITE`, `GS_ENVOL` : périmètres ciblés selon métier

### Stratégie de migration
- **Pas de refacto immédiate du code existant** : les contrôles `hasM365Group()` historiques continuent de fonctionner
- Migration progressive : les nouvelles fonctionnalités utilisent `userCan()` / `useUserCan` ; l'ancien code sera converti au fil de l'eau

---

## Dashboard widgets personnalisables (livré 24 mai 2026)

### Architecture
- Routes : `/` et `/dashboard` (même page)
- 10 widgets disponibles, filtrés à l'affichage selon les permissions de l'utilisateur
- Drag & drop via `grid-layout-plus`
- Mode édition + bouton "Ajouter un widget"
- Configuration persistée en BDD : table `user_dashboard_widgets`
- Layout par défaut selon profil M365 dominant (seeder `DashboardSeeder`)
- Cache file 5 min par widget (réduit la charge sur les requêtes coûteuses)

### Widgets disponibles
- `appels_de_fonds_en_retard`
- `factures_a_valider`
- `leads_marketing_recents`
- `synthese_chantier`
- `tresorerie_consolidee`
- `synthese_commerciale`
- `demandes_fournisseurs`
- `synchros_intacct`
- `calendrier`
- `documents_recents`

### Bug fix notable
- **Boucle infinie résolue** via comparaison `layoutSignature` (avant : le watcher se déclenchait sur chaque mutation interne du layout par `grid-layout-plus`, provoquant un re-render infini)

---

## Refonte page /admin (livré 24 mai 2026)

### Structure par onglets (visibilité selon groupes M365)
| Onglet | Groupes M365 autorisés |
|---|---|
| Utilisateurs & Droits | `GS_DSI`, `GS_ADMIN_ERP` |
| Marketing | `GS_DSI`, `GS_ADMIN_ERP`, `GS_DIRECTION_GENERALE` |
| Comptabilité & Intacct | `GS_COMPTABILITE`, `GS_DSI`, `GS_ADMIN_ERP` |
| SharePoint & Documents | `GS_DSI`, `GS_ADMIN_ERP` |
| Système | `GS_DSI` uniquement |

### UI
- Cartes compactes (max 200px), hover discret
- Header avec toggle `emails_enabled` + indicateur dernière synchro Intacct

### Bug fix
- `AdminController` : import `use App\Http\Controllers\Admin\AdminController` manquant — corrigé

---

## Refonte UX "Service client" (livré 25 mai 2026, commit `44dde03`)

> L'ancienne page TMA devient une page conteneur **"Service client"** regroupant deux sous-onglets : **TMA** et **Appels de fonds**.

### Structure
- Page conteneur "Service client" avec deux sous-onglets internes
- Hash deep-link : `#tma` (défaut) et `#appels-fonds`
- Mode "un seul onglet" si l'utilisateur n'a qu'une des deux permissions

### Routes & redirections
- `/programmes/{id}/tmas` : page conteneur Service client
- `/programmes/{id}/appels-de-fonds` : **redirection 301** vers `/programmes/{id}/tmas#appels-fonds`
- L'onglet "Appels de fonds" est **retiré** de `/programmes/{id}/edit` (la page riche AdF migre dans le sous-onglet)

### Refacto Vue
- Composants extraits : `ProgrammeTmasPanel.vue` + `ProgrammeAppelsFondsPanel.vue` (remplacent les anciens panels par la version riche)
- `AppelsDeFonds/Index.vue` devenu un wrapper minimal du panel

### Permissions
- `tma.*` et `programmes.appels_de_fonds.*` re-catégorisées dans la catégorie **"Service client"**
- Middleware `EnsureFeaturePermission` étendu pour gérer le OR (accès si l'une des deux suffit)

### Libellés
- `AppShell`, `ProgrammeNav`, Dashboard programme : libellés de navigation mis à jour

---

## Liaison Stades VEFA ↔ Chronologie programme (livré 25 mai 2026, commit `23b9252`)

### Modèle
- FK `programme_etape_id` sur `stades_avancement`, **nullable + nullOnDelete**
- Plusieurs stades peuvent pointer vers la même étape de chronologie (cardinalité N → 1)
- Warning UI **non bloquant** en cas de doublon de mapping

### Compatibilité
- Stades existants restent non rattachés ; le mapping se fait manuellement par l'utilisateur
- Validation "somme des % = 100%" conservée

### Portée
- FK **purement informationnelle** : la génération AdF reste basée sur `stade_avancement_id`, pas sur l'étape de chronologie

---

## Module Bibliothèque TMA (livré 25 mai 2026, commit `641c2f7`)

### Modèle de données

| Table | Rôle |
|---|---|
| `prestations_tma` | Catalogue global : libellé, unité, prix entreprise HT avant/après coulage, code, actif, ordre |
| `prestations_tma_programme_overrides` | `pourcentage_ecart_avant_coulage` et `pourcentage_ecart_apres_coulage` **signés**, par programme/prestation (unique) |
| `tma_lignes` | N lignes par TMA avec snapshots (`libelle`, `unite`, `prix_unitaire_entreprise_ht`), quantité, totaux entreprise HT et client HT |

### Modifications sur `tmas`
- Nouvelle colonne `moment_coulage` (`avant` / `apres`)
- `facture_ent_ht` et `facture_client_ht` deviennent **calculés** depuis les lignes
- `marche_id` devient **nullable** et **n'est plus utilisé** pour le pricing (multi-entreprises par ligne reporté à un prochain sprint)

### Pricing
- Coefficient prix client par défaut : **×1.8** (= 1.2 × 1.5)
- Préremplit le formulaire, modifiable manuellement ligne par ligne

### UI
- Bouton **"Bibliothèque TMA"** dans l'onglet TMA → `/tma/bibliotheque` (page globale)
- Bouton **"Overrides programme"** dans l'onglet TMA → `/programmes/{programme}/tma/overrides`
- Refonte du formulaire TMA : sélection moment coulage + ajout de lignes via catalogue + calcul auto des totaux + marge affichée

### Permissions (catégorie "Service client")
| Permission | Lecture | Écriture |
|---|---|---|
| `tma.bibliotheque` | `GS_DIRECTION_GENERALE` | `GS_DSI`, `GS_ADMIN_ERP`, `GS_ENVOL` |
| `tma.overrides_programme` | — | `GS_DSI`, `GS_ADMIN_ERP`, `GS_ENVOL`, `GS_DIRECTION_GENERALE` |

- Seeder **idempotent** (`updateOrCreate` / `firstOrCreate`)

### Hotfix création TMA (commit `11cfac5`, 25/05/2026)
- **Lots éligibles** : règle métier confirmée — statuts `reserve` + `acte`
- **Empty state** lots : « Aucun logement réservé ou acté sur ce programme »
- **Select Marché** : format `référence — fournisseur.nom — poste_bilan_libelle`

---

## Switch programme depuis breadcrumb (livré 25 mai 2026, commit `4284193`)

> Sélecteur de programme directement dans le breadcrumb avec recherche, pour basculer rapidement entre programmes sans repasser par le dashboard.

### Endpoint
- `/api/dashboard/programmes-switcher`
- Service `ProgrammeAccessService` :
  - `switcherOptionsForUser()`
  - `accessibleProgrammeIds()`
  - `accessibleProgrammesForUser()`
- Cache user 5 min

### Comportement navigation
- Substitution **regex** du segment `/programmes/{old_id}/` par `/programmes/{new_id}/` dans `page.url`
- **Conserve** query string + hash (ex : reste sur `#factures` après switch)
- **Fallback** dashboard programme si l'URL courante ne contient pas `/programmes/{id}/`

### 🐛 Bug en cours (Ziggy)
- `AppShell.vue` utilise `route('api.dashboard.programmes-switcher')` mais **Ziggy n'est pas installé**
- `route()` retourne `undefined` → `axios.get(undefined)` → erreur « Impossible de charger les programmes »
- **Fix prévu** : remplacer par l'URL directe `/api/dashboard/programmes-switcher`
- **Audit à faire** : vérifier qu'aucun autre `route()` Ziggy n'a été introduit ailleurs dans la session

---

## Refonte Factures en sous-onglet de Suivi Chantier (livré 25 mai 2026, commit `6981623`)

### Structure
- Onglet **"Factures"** retiré de la nav programme principale (`AppShell`)
- Devient **sous-onglet de "Suivi Chantier"**
- Ordre final des sous-onglets : `Appels d'offres | Marchés | Factures | CIE`

### Navigation
- Sous-onglets convertis de `?tab=...` vers **hash** (`#appels-offres`, `#marches`, `#factures`, `#cie`)
- **Compat ascendante** : `?tab=xxx` → `#xxx` via `history.replaceState` au chargement
- Route `/programmes/{programme}/factures` **conservée** (wrapper minimal)

### Permissions
- Middleware `feature.permission:factures.lecture` appliqué
- Filtre d'affichage du sous-onglet selon permission

### Refacto Vue
- Composant extrait : `ProgrammeFacturesPanel.vue`

---

## Tooling Meta — replay + health check (livré 26 mai 2026)

> Outillage de résilience pour le module Capture Leads Meta Ads, suite à un incident webhook (token expiré + désabonnement page).

### Commande de rattrapage
- Artisan : `php artisan meta:replay-leads` (commit `61d1b0e`)
- Endpoint admin équivalent : `POST /admin/meta/replay-leads` (commit `2d753de`)
- **Endpoint obligatoire** car le CLI OVH ne peut pas sortir en HTTPS vers Graph (voir Contraintes infra OVH)
- Usage réel : **27 leads manqués rejoués** sur l'incident 23-26/05/2026

### Health check Meta
- Job horaire qui vérifie : validité du token + état de l'abonnement webhook sur la page (id `570810992938193`)
- Page admin `/admin/meta/health` : état détaillé + bouton de réabonnement
- **Widget dashboard** dédié (état OK / KO + dernier check)
- **Bannière globale** affichée en cas de KO pour détection précoce
- Commits : `cb14a70` + suivants

---

## Refonte comptabilisation Intacct (livré 26 mai 2026, sprint debug)

> Refonte en profondeur du workflow `APBILL` pour fiabiliser la création de factures fournisseur dans Sage Intacct.

### Changements majeurs

| Avant | Après | Commit |
|---|---|---|
| Endpoint `BillCreate` (legacy) | `ExtBillCreate` (SDK natif) | `3176e6a`, `4224852` |
| `setBaseCurrency` / `setTransactionCurrency` envoyés | Retrait (déclenchait des erreurs) | `129c884` |
| Lecture APBILL par ID direct | Fallback `query` + `readByQuery` | `49d49eb` |
| SDK Intacct depuis Composer | SDK custom **restauré dans `vendor/intacct`** | (lié à `cb14a70`) |

### Endpoint debug `/admin/intacct/test-bill` (commits `c799dde`, `70e7bb4`, `30a452d`)
- Page d'investigation **pas-à-pas** pour les envois APBILL
- Champs configurables un à un : vendor, dates, montants, pièces jointes, TVA
- Bug HTTP corrigé en route : `->post` → `->send` (commit `30a452d`)
- Utilisé pour isoler les champs déclencheurs d'erreurs côté Intacct

### 🐛 Bug résiduel en cours d'investigation
- **Smart event tenant** `UPDATE_REFERENCE_NUMBER` plante systématiquement **après** un `CREATE APBILL` réussi.
- Côté code ERP : `ExtBillCreate` + custom field `NUMROTATION_INTERNE` sont alignés sur le script de référence qui fonctionne en prod chez Hectare.
- **Prochaine piste** : ajouter `taxentries` (`BillLineTaxEntriesCreate`) par ligne avec `detailid` `TR2575FRMTPB2BFRMTGDSGLSTDRT` (TVA 20%) dans le test-bill pour valider le format complet.

---

## Référentiel TVA Sage Intacct

> Codes `detailid` à utiliser dans les `taxentries` lors des `ExtBillCreate` / `BillLineTaxEntriesCreate`.

**Solution de taxe** : `TVA française - SYS`

### Comptes 604xxx (frais BS — TVA déductibles principales)

| Taux | `detailid` |
|---|---|
| 20% | `TR2575FRMTPB2BFRMTGDSGLSTDRT` |
| 10% | `TR2576FRMTPB2BFRMTGDSGLREDRT1` |
| 5,5% | `TR2577FRMTPB2BFRMTGDSGLREDRT2` |
| Exonéré 0% | `TR2578FRMTPB2BFRMTGDSGLEXMPT` |

### Comptes 2xxx (immobilisations)
- Utiliser les variants **"FR -Immos..."** : `TR2488xxx`, etc.

---

## Décisions métier prises — chantiers à venir (mai 2026)

> Décisions actées avec Robin, à implémenter dans les sprints suivants.

### Dérogation PMR (TMA)
- Toggle **"Dérogation PMR"** sur la fiche TMA
- Si activé : génération d'un PDF de dérogation destiné à l'acquéreur (signature électronique prévue en phase 2) + bureau de contrôle
- Bureau de contrôle = **FK fournisseurs Intacct**, sélectionnable dans les paramètres du programme
- Nouvelle bibliothèque **"Réversibilité"** (libellé UI), table technique `prestations_reversibilite_pmr` : `{libellé, texte paragraphe PDF}`
- Accès via bouton dans l'onglet TMA de Service client
- Permission : `GS_ENVOL`
- Stockage du PDF : SharePoint, dossier acquéreur
- **Bloqueur** : attente d'un exemple PDF fourni par Robin pour caler la structure de base commune

### Facturation TMA
- Toggle `facturation_tma_via_envol` sur `programmes` (défaut **`true`**)
  - `true` : RIB Envol fixe (table `parametres` globale, modifiable via `/admin`)
  - `false` : RIB du programme
- Numérotation **TMA** : `TMA-{code_societe}-{annee}-{seq}` côté ERP + `FAC-XXX` Sage
- **Même pattern asynchrone** que les AdF VEFA (numero_interne ERP + numero_facture Intacct)
- `CLASSID` Intacct : code analytique du programme (`PRG-{dpt}-{code}`)
- Compte produit Intacct TMA : paramétrable via `/admin` (défaut **`707201`** — nomenclature Flora)

### Trésorerie (refonte complète, à reprendre)
- Repartir de la **structure du bilan** (postes par rubrique)
- Colonnes : `Poste | Étude fi | Reste à payer | M1 | M2 | ...` (à partir du mois de la 1ère facture rentrée)
- `Reste à payer = (marchés + avenants signés) − factures validées`
- **TTC partout**
- 2 filtres : masquer postes à 0 + masquer postes 100% payés
- **Recettes commerciales** :
  - Lot **acté** : chronologie réelle + % stades VEFA + 30j d'encaissement
  - Lot **réservé** : date prévisionnelle d'acte + chronologie prévisionnelle + 30j
  - Lot **disponible** : date objectif d'acte + idem
- **Inconnues à trancher** :
  - périmètre "déjà dépensé" (validé vs payé)
  - étalement des dépenses futures
  - date de référence
  - TVA poste par poste
  - source "date objectif acte"
  - supprimer ou garder l'existant

---

## Manuel utilisateur (en cours)

> Documentation utilisateur de l'ERP, à destination des équipes Hectare.

### Phase 1 — Rédaction Markdown
- Rédaction structurée par modules métier
- Géré sur un onglet Claude dédié

### Phase 2 — Intégration dans l'ERP (via Cursor)
- Route `/aide` accessible depuis l'ERP
- Moteur de recherche full-text dans la doc
- Chatbot IA pour répondre aux questions utilisateurs en s'appuyant sur le manuel

---

## Organisation des sessions Claude

- **3 onglets Claude en parallèle** :
  1. **Dev** — chef d'orchestre des sessions de développement (Cursor en local)
  2. **Manuel** — rédaction du manuel utilisateur
  3. **PROJECT.md** — maintenance de ce fichier de contexte
- **Claude Code** adopté en complément de Cursor depuis le 26/05/2026 pour les sessions de debug intensives (lecture/écriture directe du repo, exécution shell, moins d'allers-retours sur les chantiers complexes type Intacct)
- Licence **Claude MAX** active : marge confortable sur la longueur des conversations

---

## En cours

> _(Mettre à jour à chaque session)_

- [x] Module Capture Leads Meta Ads en production
- [x] Refonte politique emails (2 actifs / reste désactivé)
- [x] Édition inline commercial (fiche lead + codes campagnes)
- [x] Provisioning auto users M365 préapprouvés
- [x] Spec module Appels de Fonds validée + mockup PDF validé
- [x] **Sprints 1-6 module Appels de Fonds VEFA déployés en prod (23/05/2026)**
  - Sprint 1 : coordonnées société & bancaires (programmes)
  - Sprint 2 : stades d'avancement VEFA (table + UI drag & drop)
  - Sprint 3 : génération AdF + numérotation AF-{code}-{annee}-{seq}
  - Sprint 4 : PDF charte Envol (template Blade)
  - Sprint 5 : workflow Intacct asynchrone (numero_interne + numero_facture, retries, dashboard erreurs)
  - Sprint 6 : UI génération batch + polling + envoi acquéreur désactivé en rodage
- [x] Bug chronologie programme — correctif finalisé et déployé en prod le 23/05/2026 (commit `7e56d2b`) : layout tableau inline pleine largeur + barre fixe Enregistrer + classe `chronologie-tab-bleed` pour bypass `max-w-6xl` — fichier `resources/js/Components/ProgrammeChronologieEtapesPanel.vue`
- [x] **Système de droits par fonctionnalité livré (24/05/2026)** — features_permissions + UI /admin/droits + helper userCan() + middleware feature.permission + cache 5 min
- [x] **Dashboard widgets personnalisables livré (24/05/2026)** — 10 widgets, drag & drop, layout par user, cache 5 min, bug boucle infinie résolu (layoutSignature)
- [x] **Refonte page /admin livrée (24/05/2026)** — onglets par catégorie + header (toggle emails + synchro Intacct)
- [x] Bug AdminController résolu (import `use App\Http\Controllers\Admin\AdminController` manquant)
- [x] **Refonte UX Service client (25/05/2026, commit `44dde03`)** — TMA + AdF regroupés, sous-onglets avec deep-link, redirection 301
- [x] **Liaison Stades VEFA ↔ Chronologie (25/05/2026, commit `23b9252`)** — FK informationnelle nullable
- [x] **Module Bibliothèque TMA (25/05/2026, commit `641c2f7`)** — catalogue global, overrides programme, lignes snapshotées, coefficient ×1.8
- [x] **Hotfix création TMA (25/05/2026, commit `11cfac5`)** — empty state lots (`reserve` + `acte`) + format select Marché
- [x] **Switch programme depuis breadcrumb (25/05/2026, commit `4284193`)** — endpoint + service + cache 5 min — ⚠️ **BUG Ziggy en prod, fix en cours**
- [x] **Refonte Factures en sous-onglet Suivi Chantier (25/05/2026, commit `6981623`)** — hash deep-link + compat `?tab=`
- [x] **Module Meta : webhook restauré (sprint 23-26/05/2026)** — token renouvelé + abonnement page `570810992938193` rétabli, **27 leads manqués rejoués** via `/admin/meta/replay-leads`
- [x] **Refonte comptabilisation Intacct (26/05/2026)** — `BillCreate` → `ExtBillCreate` (SDK natif), retrait `setBaseCurrency` / `setTransactionCurrency`, fallback `query` + `readByQuery`, SDK custom restauré dans `vendor/intacct`
- [x] **Health check Meta poussé (26/05/2026, commit `cb14a70` + suivants)** — job horaire + widget dashboard + bannière globale + page `/admin/meta/health`
- [ ] **🐛 Bug Intacct résiduel** : smart event tenant `UPDATE_REFERENCE_NUMBER` plante après `CREATE APBILL`. Debug via `/admin/intacct/test-bill` en cours pour isoler le champ déclencheur. Code ERP : `ExtBillCreate` + custom field `NUMROTATION_INTERNE` alignés sur le script de référence qui marche en prod.
- [ ] **Prochaine étape Intacct** : ajouter `taxentries` (`BillLineTaxEntriesCreate`) par ligne avec `detailid` `TR2575FRMTPB2BFRMTGDSGLSTDRT` (TVA 20%) dans le test-bill pour valider le format complet
- [ ] **🐛 Fix bug Ziggy switch programme** : remplacer `route('api.dashboard.programmes-switcher')` par URL directe dans `AppShell.vue` + audit du reste de la session
- [ ] **Bibliothèque Réversibilité + bureau de contrôle programme** (prérequis Dérogation PMR)
- [ ] **Dérogation PMR : génération PDF** (en attente exemple PDF fourni par Robin)
- [ ] **Facturation TMA + workflow Intacct asynchrone** (TMA-XXX + FAC-XXX, même pattern que AdF VEFA)
- [ ] **Trésorerie : refonte complète** (structure du bilan, colonnes mensuelles, recettes par statut de lot) — plusieurs inconnues à trancher
- [ ] **Tests en prod du module Appels de Fonds (Sprints 1-6 déployés mais toujours pas testés)**
- [ ] Logo + pattern PNG à uploader dans `resources/assets/` (bloque la génération propre des PDF AdF)
- [ ] Validation acompte à l'acte avec compta avant ajout
- [ ] Migration progressive du code existant vers le helper `userCan()` (au fil des évolutions)
- [ ] **Ticket OVH ouvert** : limite upload 128M (bloque les AO > 350 Mo)
- [ ] Manuel utilisateur (onglet dédié, phase 1 Markdown)
- [ ] Multi-tenant Meta leads (4 sociétés HECTARE/Envol/Gemme/Les Balcons de la Cité)
- [ ] Module CIE
- [ ] Module Juridique/Contentieux

---

## Comment utiliser ce fichier

1. **Début de session** : coller ce fichier entier dans le chat Claude
2. **Pendant la session** : travailler sur un module ou une fonctionnalité précise
3. **Fin de session** : demander à Claude de mettre à jour ce fichier avec les avancées
4. **IDE recommandé** : Cursor (lit toute la codebase, garde le contexte technique)
