01 Avancement par sprint
S61
Terminé
Fondations BDD + Auth
4 tables BDD · 8 routes auth/accès
- 4 tables : portail_client_acces, portail_client_session, portail_client_notification, portail_client_action
- Auth login/logout par token (64 chars hex)
- Page /app/parametres/portail v1
- Admin : créer/révoquer accès
S62
Terminé
Animaux, CAC, Devis, Factures
7 routes · Modal PDF · Historique CAC
- GET /portail/animaux — avec score CAC
- GET /portail/animaux/:id/cac — historique
- GET /portail/devis — ENVOYE/ACCEPTE/FACTURE
- GET /portail/factures + /:id/pdf — modal iframe
- Modal CAC avec graphique barres
S63
Déployé ✓
Déploiement complet + Email
11 routes · nodemailer · Toggle · 4 points d'entrée
- Routes portail migrées vers instance.use()
- Colonnes BDD corrigées (ANI_CLI, SEA_DATE_DEBUT…)
- Page /client/[token] — 4 onglets (séances, factures, animaux, notifications)
- nodemailer ^6.9.14 — envoi lien par email SMTP
- Toggle activer/désactiver accès
- Email pré-rempli depuis TIE_EMAIL fiche client
- 4 points d'entrée : sidebar, URL directe, liste clients, fiche client
- Test validé : login OK, 5 animaux, 4 séances, 8 factures (Catherine Deneuve)
02 Fonctionnalités déployées S63
Authentification par token
Lien tokenisé (64 chars hex) envoyé par email SMTP. Login automatique à l'ouverture de l'URL. Session stockée en sessionStorage exclusivement (jamais localStorage).
Séances & Confirmations
Liste des séances du client (SEA_DATE_DEBUT). Confirmation/Annulation/Report depuis le portail via POST /portail/seances/:id/confirmer.
Animaux
Liste des animaux du client connecté (ANI_CLI). Score CAC courant, historique des bilans comportementaux.
Factures
Solde restant par facture, règlements. PDF rendu dans une modal iframe — jamais window.open(). Chargement lazy à l'ouverture de l'onglet.
Notifications
Notifications client (PCN_TYPE, PCN_CANAL, PCN_STATUT, PCN_OBJET). Colonnes réelles BDD portail_client_notification.
Admin Portail
Page /app/parametres/portail : select 500 tiers, email auto depuis TIE_EMAIL, copier lien 📋, envoyer ✉️, toggle ✓/✗. Stats : accès créés / actifs / connexions.
03 Toutes les routes API (S61 + S62 + S63)
| Méthode | Route | Description | Sprint |
|---|---|---|---|
| POST | /portail/auth/login | Connexion client via token accès → session_token | S61 |
| POST | /portail/auth/logout | Déconnexion, invalidation session | S61 |
| GET | /portail/admin/acces | Liste des accès portail (praticien) | S61 |
| POST | /portail/admin/acces | Créer accès + générer token 64 chars | S61 |
| GET | /portail/animaux | Animaux du client connecté (ANI_CLI) | S62 |
| GET | /portail/animaux/:id/cac | Historique CAC (vue + fallback) | S62 |
| GET | /portail/devis | Devis ENVOYE/ACCEPTE/FACTURE | S62 |
| GET | /portail/devis/:id | Détail + lignes + signature | S62 |
| GET | /portail/factures | Factures + solde restant | S62 |
| GET | /portail/factures/:id | Détail + lignes + règlements | S62 |
| GET | /portail/factures/:id/pdf | PDF facture pour modal iframe | S62 |
| GET | /portail/seances | Séances du client (SEA_DATE_DEBUT) | S63 |
| POST | /portail/seances/:id/confirmer | CONFIRME / ANNULE / REPORTE | S63 |
| GET | /portail/notifications | Notifications client (colonnes PCN_*) | S63 |
| PUT | /portail/admin/acces/:id/toggle | Activer / désactiver un accès | S63 |
| POST | /portail/admin/acces/:id/send-link | Envoyer lien portail par email (nodemailer) | S63 |
| PUT | /param-smtp | Sauvegarde config SMTP depuis UI | S63 |
ℹ️ Toutes les routes portail utilisent le helper _readBody() (body non parsé par NestJS avant instance.use()). Routes dans instance.use() exclusivement (jamais app.use()).
04 Tables BDD — colonnes réelles
| Table | Colonnes clés | Notes |
|---|---|---|
| portail_client_acces | PCA_ID, PCA_TOKEN, PCA_ACTIF, PCA_DATE_EXPIRATION, PCA_EMAIL, TIE_ID | Token 64 chars hex, lié au tiers client |
| portail_client_session | PCS_SESSION_TOKEN, PCS_DATE_FIN, PCS_ACTIF, PCA_ID | Session active après login |
| portail_client_notification | PCN_TYPE, PCN_CANAL, PCN_STATUT, PCN_OBJET, PCN_DATE_CREATION, TIE_ID | Canal : EMAIL / SMS |
| portail_client_action | PCA_ACTION, PCA_DATE, PCA_IP, PCS_ID | Log des actions client |
⚠️ Colonnes importantes : animal.ANI_CLI (pas TIE_ID) · seance.SEA_DATE_DEBUT (pas SEA_DATE) · tiers.TIE_RAISON_SOCIALE (pas TIE_NOM/PRENOM)
05 Points d'entrée portail (S63)
1
URL directe
http://[host]/client/[TOKEN_64_chars]
Login automatique à l'ouverture. Token envoyé par email ou copié depuis la page admin.
2
Sidebar — Communauté → 🔗 Portail Client
/app/parametres/portail
Page admin portail complète avec liste de tous les accès créés.
3
Liste clients — bouton 🔗 Portail par ligne
/app/app/clients
Mini-modal avec statut accès + bouton copier lien ou créer accès.
4
Fiche client — bouton 🔗 Portail dans PageHeader
/app/app/clients/[id]
Accès direct depuis la fiche individuelle du client.
06 Règles techniques portail
✅ Toutes les routes dans
✅ Body parsing via helper
✅ sessionStorage exclusivement côté client (jamais localStorage)
✅ PDF factures en modal iframe uniquement (jamais window.open())
✅ getDb() par connexion avec db.end() en finally
✅ nginx strips /api/ prefix → routes définies sans /api/
✅ Eliot = option commerciale, toutes fonctionnalités portail marchent sans lui
instance.use() exclusivement (jamais app.use())✅ Body parsing via helper
_readBody() sur toutes les routes POST/PUT✅ sessionStorage exclusivement côté client (jamais localStorage)
✅ PDF factures en modal iframe uniquement (jamais window.open())
✅ getDb() par connexion avec db.end() en finally
✅ nginx strips /api/ prefix → routes définies sans /api/
✅ Eliot = option commerciale, toutes fonctionnalités portail marchent sans lui