# Module Perfex « Espace Bénéficiaire » — Documentation technique

**Version : 1.1.2** (2026-07-09) · Auteur : MyISI · Déployé + E2E validé sur **s-mob.fr** (Perfex 3.4.1, PHP 8.2, OVH cluster026)
Source : `C:\Users\loicg\claude\symbiose-mobilite\plugin\modules\espace_beneficiaire\` · Archive : `espace_beneficiaire-v1.1.2.zip`

## 1. Ce que fait le module

Espace client **dédié et cloisonné** pour les « bénéficiaires » (personnes accompagnées par l'entreprise : relocation, immigration, recrutement…), distinct du client mandataire (B2B). Générique et revendable (branding paramétrable).

- **Lien contact ↔ projet(s)** : case « Bénéficiaire » dans la modale contact + page admin dédiée (N bénéficiaires/projet, N projets/bénéficiaire).
- **Portail « Mon dossier »** (`/espace_beneficiaire`) : vue à onglets **Synthèse / Documents / Discussion / Étapes** (onglets activables PAR PROJET). La vue projet native n'est JAMAIS montrée à un bénéficiaire (redirection totale, pas de masquage CSS).
- **Synthèse** : % avancement (tâches status 5 / total), **point de situation MARC** (IA Ollama + repli gabarit + cache TTL), infos clés (éditées admin), demandes de pièces avec upload.
- **Pièces justificatives PAR PROJET** (onglet « Pièces (Bénéficiaire) » dans la vue projet admin) : catalogue de pièces réutilisables (+ indice MARC), **lots** (ex. « Dossier visa »), demande libre ; cycle pending → uploaded → validated ; boutons **Valider / Redemander (invalide) / Relancer MARC / Supprimer**.
- **MARC** (Module d'Analyse et de Reconnaissance de Conformité — nom de l'IA côté s-mob) :
  - *Pré-check vision* d'une pièce uploadée (image) : conforme → **auto-validation** ; non conforme → badge rouge + note ; PDF/incertain → vérification manuelle.
  - *Titrage* des dépôts libres (« Facture EDF juin 2026 — Karim Testeur.png »).
  - *Point de situation* narré (texte) — ne dit JAMAIS « finalisé » tant que le statut projet ≠ Terminé (4).
  - *Suggestions FAQ* : MARC lit la conversation + la liste des articles KB du CRM et choisit les pertinents (repli scoring mots-clés).
- **Renommage auto** des fichiers : « {Pièce} — {Prénom Nom}.ext ».
- **Export PDF templétisé** : template HTML + champs de fusion éditable dans les réglages (TCPDF ; tables + inline uniquement, PAS d'emoji ni CSS moderne). Template démo fourni.
- **Discussion** : fil dédié par lien (tables NATIVES tblprojectdiscussions/comments, créé paresseusement « Échanges — {prénom} »), rendu par le module en bulles chat, notifications staff in-app.
- **Garde-fous** : redirection forcée au login ; whitelist URI (profile/gdpr/change_language) ; `clients/project/{id}` → `espace_beneficiaire/dossier/{id}` si lié, sinon refus ; tout le reste → dashboard. Liens thème (Fichiers/Calendrier/Support/Projets) masqués via CSS `app_customers_head`.

## 2. Architecture

```
espace_beneficiaire.php        init : hooks (admin_init, after_contact_modal_content_loaded,
                               contact_created/updated, before_create/update_contact (FILTRES CRITIQUES),
                               clients_init, after_contact_login, after_clients_area_init, app_customers_head)
install.php / uninstall.php    schéma idempotent + options + template PDF par défaut
controllers/Espace_beneficiaire.php  portail (ClientsController + ValidatesContact) : index, dossier,
                               discussion_post, download (sécurisé), refresh_summary, upload_request,
                               upload_free, pdf
controllers/Ebenef_admin.php   admin : liens, key_infos(+tabs), catalogue pièces/lots (CRUD + édition),
                               request_pieces, doc_request_status/invalidate/recheck/delete,
                               regenerate_summary, apply_profile, pdf_preview, customer_data (AJAX)
libraries/Ebenef_summary.php   point de situation (collect → template | ollama gpt-oss) + cache
libraries/Ebenef_ai.php        MARC vision : check_document, suggest_title (images uniquement, ≤8 Mo)
libraries/Ebenef_merge.php     champs de fusion PDF ({avancement_pct}, {infos_cles_table}…)
libraries/Ebenef_pdf.php       extends App_pdf (TCPDF) → writeHTML(template fusionné)
models/Ebenef_model.php        liens, key_infos, doc_requests, types/lots, summaries, tabs/projet,
                               fichiers visibles, discussion, kb_suggestions (MARC-first), apply_beneficiary_profile
views/client/{dashboard,dossier}.php · views/admin/{manage,key_infos,project_tab,contact_checkbox,settings_tab}.php
views/pdf_wrapper.php · views/admin/pdf_template_default.html · language/{french,english}/
```

## 3. Base de données (7 tables, AUCUN ALTER du core)

| Table | Rôle |
|---|---|
| `tblebenef_links` | contact_id, project_id (UNIQUE couple), discussion_id, active, addedfrom |
| `tblebenef_key_infos` | project_id, label, value, sort_order, visible |
| `tblebenef_doc_requests` | link_id, title, description, status ENUM(pending/uploaded/validated), file_id, doc_type_id, **ai_status** (none/match/mismatch/unknown), **ai_note** |
| `tblebenef_doc_types` | catalogue : name, description, **ai_hint**, active |
| `tblebenef_doc_bundles` / `_items` | lots (name) / (bundle_id, doc_type_id) |
| `tblebenef_summaries` | project_id UNIQUE, content, source (ai/template), model, generated_at |

Réglages par projet : `tblproject_settings` → `ebenef_tabs` (serialized documents/discussion/milestones).
**9 options** `ebenef_*` : ollama_api_key, ollama_model (texte, `gpt-oss:120b`), **ollama_vision_model** (`gemma4:31b-cloud` sur s-mob, vide = MARC off), summary_ttl_hours (24), branding_color, branding_logo_url, beneficiary_label, allow_free_uploads, pdf_template.

## 4. Pièges Perfex/MX appris (LOAD-BEARING)

1. **Champs custom dans la modale contact** : le core add/update_contact() envoie TOUT le POST dans l'INSERT/UPDATE tblcontacts → « Unknown column » → modale figée. **Obligatoire** : filtres `before_create_contact`/`before_update_contact` qui `unset()` les champs custom (les hooks post-save lisent `$_POST` directement).
2. **Init modules** chargés à CHAQUE requête via `application/hooks/InitHook.php` en `pre_controller_constructor` → les hooks d'init sont enregistrés à temps pour les constructeurs.
3. **Routing MX** : URL publique `<module>/<method>` sans routes.php SI le contrôleur porte le nom du module ; `admin/<module>/<controller>/<method>` (le routeur strippe `admin/` quand segment2 est un module).
4. **Garde-fous portail** : hook `after_clients_area_init` (constructeur du core Clients.php:19) fire sur chaque page native, PAS dans nos contrôleurs → pas de récursion.
5. **PDF = TCPDF** (pas mPDF) : `App_pdf` abstract (prepare/file_path/type), `app_pdf($type, $path, ...$args)`, la vue reçoit `$pdf` → `writeHTML`. Tables + styles inline SEULEMENT ; **pas d'emoji** (helvetica → « ?? »).
6. **Téléchargements** : `while(ob_get_level())ob_end_clean()` + zlib off + **PAS de Content-Length** (mod_deflate OVH corrompt sinon).
7. **Fichiers projet** : remplir `original_file_name` ET `subject` sinon nom vide dans l'UI.
8. **Perfex 3.4 = Font Awesome 6** : pas de noms FA4 à suffixe -o (`fa-file-pdf-o` → `fa-regular fa-file-pdf`).
9. **OVH mutualisé : sortant HTTPS REFUSÉ depuis le shell SSH mais AUTORISÉ depuis PHP web** → tester les APIs externes par le chemin web, jamais en CLI.
10. Onglet projet admin : `$CI->app_tabs->add_project_tab($slug, [name, icon, view (vue module), position])` — la vue reçoit `$project`.
11. Contacts : login = `password_hash()` bcrypt compatible ; `email_verified_at` requis (ValidatesContact) ; permission « projets » = permission_id **6** dans tblcontact_permissions.
12. États tâches : 1 Non commencée, 2 En cours, 3 En Test, 4 Attente feedback, 5 Achevée. Étape « en cours » si done>0 OU active(2/3/4)>0.

## 5. Ollama cloud (MARC)

- `POST https://ollama.com/api/chat` · `Authorization: Bearer <clé>` · `{"model","stream":false,"messages":[...]}` → `message.content` ; vision = `images:[base64]` sur le message user.
- Timeouts : 60 s (texte) / 90 s (vision) — cold start des modèles cloud.
- RGPD : envoi minimal (noms d'étapes/statuts/libellés ; image de la pièce uniquement pour le pré-check).

## 6. Déploiement / maintenance

- **Lint-gated deploy** : zip → SFTP `/homez.1014/symbior` (Posh-SSH, creds Bitwarden s-mob) → unzip stage → `php -l` sur tout → move vers `smob.fr/modules/espace_beneficiaire`.
- Module DÉJÀ ACTIF : le hook d'activation ne rejoue pas → **migrations par script PHP via SSH** (voir `plugin/ebenef_migrate11.php` modèle).
- Compte test : client 8 « ZZTEST Beneficiaire », contact 5 Karim Testeur (`loic+ebenef-test@goaper.fr` / `EbenefTest2026!`), projet 18. Reseed/wipe : `plugin/ebenef_seed.php`.

## 7. Historique versions

- **1.0.0** : socle (liens, portail, garde-fous, docs, résumé, PDF).
- **1.0.1** : fix modale contact (filtres) ; vue dossier à onglets remplaçant le natif ; réglages onglets/projet ; masquage thème ; FA6.
- **1.1.0** : pièces PAR PROJET (onglet projet), catalogue + lots, renommage auto, pré-check MARC vision, titrage IA, sidebar FAQ.
- **1.1.1** : MARC (nom), FAQ choisie par l'IA, Redemander/Relancer MARC, fix download corrompu, statuts tâches corrects (étapes « en cours » si tâches actives), jamais « finalisé » si projet non Terminé.
- **1.1.2** : édition du catalogue (pièces + lots, crayon + formulaire pré-rempli).
