# Chatbot d'actions VITALIS

Service chatbot distant (backend Laravel + widget a venir), code totalement
separe de `prestataireprod/` et `productionprod/`, integre via un lien/widget
pose sur `Vue/gabarit.php` de chaque plateforme.

## Decouverte importante : ancien prototype embarque

En cherchant le point d'integration, un chatbot **deja embarque directement
dans `prestataireprod`** a ete trouve (`Vue/chatbot_widget.php`,
`Service/Chatbot.php`, `Service/ChatbotOllama.php`, `Service/ChatbotSql.php`,
`Modele/Chatbot.php`, `Controleur/ControleurAjaxchatbotfeuille.php`,
`Controleur/ControleurAjaxchatbotia.php`), anterieur a ce projet. Il gere une
reinitialisation de **feuille de maladie** (`sp_p_reinitialiserfeuille`) avec
une couche IA (Ollama local) en texte libre.

Decision actee : **cet ancien prototype n'est pas la base du projet actuel**.
Il reste en place tel quel (non supprime, non modifie) mais n'est pas
reutilise.

## Structure du dossier

- `catalogue/bons_pec.php` : catalogue d'actions pilote (reinitialisation bon
  consultation/pharmacie/optique + consultation d'etat), charge tel quel comme
  config Laravel (`config/chatbot.php` -> `config('chatbot.actions')`).
- `catalogue/contexte_session.php` : mapping des noms de variables de session
  entre les deux plateformes (elles ne sont pas nommees pareil).
- `service/` : le backend Laravel (Phase 2, voir plus bas).

## Correction majeure de schema (importante)

Les numeros de bon **ne vivent pas dans `p_bonpec`** (table quasi vide/obsolete,
~938 lignes) mais dans des colonnes dediees de **`p_feuillemaladie`** :
`numeroBonConsultation`, `numeroBonOrdonnance`, `numeroBonOptique`. Verifie en
reel sur le bon **456730** (attention : ce numero existe a la fois comme
`numeroFeuilleMaladie` d'UN dossier et comme `numeroBonConsultation` d'un
dossier COMPLETEMENT DIFFERENT - toujours filtrer sur la bonne colonne).

Requete de lecture prealable (commune aux 3 types de bon, seule la colonne
filtree change) :

```sql
SELECT A.nomBeneficiaire, A.prenomsBeneficiaire,
       B.numeroFeuilleMaladie, B.numeroBonConsultation, B.numeroBonOrdonnance,
       B.numeroPrescription, B.numeroBonOptique, B.numeroOptique, B.facture,
       C.codePrestataire, C.libelle AS prestataire, C.codeTypePrestataire
FROM beneficiaire A
JOIN p_feuillemaladie B ON (B.idBeneficiaire = A.id)
LEFT JOIN prestataire C ON (C.codePrestataire = B.codePrestataire)
WHERE B.<numeroBonConsultation|numeroBonOrdonnance|numeroBonOptique> = ?
LIMIT 1
```

### Procedures de reinitialisation (fournies par le demandeur)

| Action | Procedure | Parametres |
|---|---|---|
| Bon consultation | `sp_perso_reinitialiserfeuille` | `numeroBonConsultation` (BIGINT), `codePrestataire` (VARCHAR) |
| Bon pharmacie (ordonnance) | `sp_perso_reinitialiserprescription` | `numeroBonConsultation`/`numeroBonOrdonnance` (BIGINT, memes valeurs sur nos tests), `codePrestataire` (VARCHAR) |
| Bon optique | `sp_perso_reinitialiserfeuille_optique` | `numeroBonOptique` (BIGINT), `codePrestataire` (VARCHAR) |

**`codePrestataire` n'est jamais demande a l'utilisateur** : deduit
automatiquement de la lecture prealable pour consultation/optique. **Cas
particulier pharmacie** : un bon ordonnance peut etre facture par plusieurs
pharmacies differentes (confirme en reel : le bon 456730 a ete facture par
`PR0940` ET `PR1175`) — le `codePrestataire` envoye a
`sp_perso_reinitialiserprescription` doit etre **choisi par l'utilisateur
parmi la liste retournee par `lecture_prealable_facturation`** (pas le
prestataire de la consultation), car la procedure filtre ses suppressions sur
ce code precis.

### Ce que font vraiment ces procedures (inspecte via `SHOW CREATE PROCEDURE`, jamais execute a l'aveugle)

Chacune des 3 procedures est auto-protegee et renvoie un diagnostic (`statut`)
sans forcement rien modifier :

| `statut` renvoye | Signification | Modifie des donnees ? |
|---|---|---|
| `BON_INTROUVABLE` | Aucun `numeroFeuilleMaladie` ne correspond | Non |
| `AUCUNE_FACTURE_NON_PHAR` / `AUCUNE_FACTURE_PHAR_PRESTATAIRE` / `AUCUNE_FACTURE_OPT` | Pas de facture de ce type pour ce prestataire | Non pour pharmacie/optique. **Pour consultation, appelle quand meme en cascade l'ancienne procedure `sp_p_reinitialiserfeuille`** (no-op si rien a reinitialiser, mais reste un effet de bord a connaitre) |
| `DEJA_DECOMPTE` | Facture deja integree a un decompte | Non, "on ne touche a rien" |
| `REINITIALISE` | Cas normal | **Oui** : insertion de sauvegarde dans `historiquereinitialiserfeuille` puis suppression/mise a jour des factures et prestations reelles pour ce prestataire |

Le service Laravel capture ce `statut` (`ChatbotActionService::executerAction`)
plutot que de supposer un succes generique : seul `REINITIALISE` est journalise
comme `succes` dans `chatbot_historique`.

### Regle de confirmation productionprod (et pharmacie sur les 2 plateformes)

Avant toute reinitialisation sur `productionprod` (et pour la pharmacie sur les
deux plateformes), le bot DOIT :
1. afficher beneficiaire + prestataire emetteur (`lecture_prealable`) ;
2. pour la pharmacie, lister tous les prestataires facturants (`lecture_prealable_facturation`) et faire choisir lequel ;
3. demander une confirmation explicite avant d'appeler la procedure d'action.

## Contexte de session : integration posee sur les gabarits

Le bloc de contexte (signe HMAC-SHA256) a ete ajoute directement dans
`Vue/gabarit.php` de chaque plateforme (juste avant `</body>`) :

- `prestataireprod/Vue/gabarit.php` : transmet `codeSociete`, `login`,
  `codePrestataire`, `codeTypePrestataire` (confirme present en session, pose
  par `ControleurConnexion.php` sous la cle `p_codeTypePrestataire_C`).
- `productionprod/Vue/gabarit.php` : transmet `codeSociete`, `login`,
  `codePrestataire` (pas de type prestataire : acces complet).

Deux variables JS sont exposees : `window.VitalisChatbotContexte` (objet, pour
lecture facile) et **`window.VitalisChatbotContexteJson`** (chaine brute EXACTE
ayant servi a la signature — c'est celle-la qu'il faut renvoyer telle quelle a
l'API, jamais la reserialiser en JS, sous peine de casser la verification HMAC
cote serveur). Le secret est lu via `Configuration::get('chatbot_hmac_secret')`
(cle dans `Config/prod.ini` des deux plateformes).

Le `<script src=".../widget.js">` reste en commentaire (TODO) : sera active une
fois le widget construit et heberge.

## Phase 2 : backend Laravel (`service/`)

Construit et teste :

- **Connexion `vitalis`** (`config/database.php`) vers la base partagee
  `finish_one` (145.239.10.133:30306) — separee de la connexion Laravel par
  defaut (sqlite) pour ne jamais faire migrer les tables internes de Laravel
  vers la production.
- **`config/chatbot.php`** : charge le catalogue + le secret HMAC.
- **`app/Services/ChatbotContexteService.php`** : vérifie la signature HMAC et
  la fraicheur du contexte (perime au-dela de 300s).
- **`app/Services/ChatbotActionService.php`** : resolveur de permissions
  (`listerActionsAutorisees`), lecture prealable, liste de facturation
  pharmacie, execution + journalisation dans `chatbot_historique`.
- **Routes API** (`routes/api.php`) : `POST /api/chatbot/menu`,
  `POST /api/chatbot/lecture-prealable`, `POST /api/chatbot/executer`. Le
  controleur re-verifie systematiquement cote serveur que l'action demandee
  fait partie du menu autorise (ne fait jamais confiance a ce que le widget a
  affiche).
- **CORS** configure (`config/cors.php`), origines a restreindre plus tard via
  `CHATBOT_ALLOWED_ORIGINS`.

Teste en HTTP reel (lecture seule uniquement) : `menu` (permissions correctes
par type de prestataire), `lecture-prealable` (bon 456730, donnees exactes
confirmees), `listerPrestatairesFacturation` (PR0940 + PR1175 confirmes).

**`/executer` n'a jamais ete appele sur une vraie procedure de reset** : sur
demande explicite, aucun test mutant n'a ete lance sur le bon 456730 (aurait
reellement supprime la facture PHAR de PR0940 ou PR1175). A faire des qu'un bon
de test non-critique (ou l'accord explicite d'impacter un bon reel) sera
disponible.

## Points ouverts restants

1. **Valeurs de `codeTypePrestataire`** pour la consultation : `PHA` et `OPT`
   sont confirmes, mais les types medicaux (`CSO`, `HPP`, `HPC`, `CME`, `DEN`,
   `LAB`, `IMA`, `SEA`...) et leur lien exact avec `codeTypeBon = CONS` restent
   a confirmer via `p_typeprestataire`. `types_prestataire_autorises` de
   l'action consultation reste a `null` (ouverte a tous types non pharmacie/optique).
2. **Origines CORS reelles** des deux plateformes a renseigner avant mise en prod.
3. **`/executer` jamais teste en reel** (voir ci-dessus).

## Prochaine etape

Widget (bulle de chat + logique de menu guide), branche sur les 3 routes API
existantes, puis activation du `<script src>` sur les deux gabarits.
