petitspas/docs/10_DATABASE.md
Julien Martin a5dae7a017 docs: Workflow création de compte + refonte documentation
- Ajout Cahier des Charges v1.3
- Ajout Workflow technique création de compte (v1.0)
- Réorganisation docs avec préfixes numériques (00_, 01_, etc.)
- Ajout données de test CSV
- Modifications principales :
  * Champ téléphone unique (suppression mobile/fixe)
  * Inscription sans mot de passe (Parents + AM)
  * Création MDP par email après validation (7j)
  * Genre enfant obligatoire (H/F)
  * Date agrément obligatoire pour AM
2025-11-25 00:28:35 +01:00

422 lines
14 KiB
Markdown

# 🗄️ Documentation Base de Données
## Vue d'ensemble
L'application PtitsPas utilise **PostgreSQL 14** avec l'extension **pgcrypto** pour la gestion des UUID.
**Nom de la base** : `ptitpas_db`
**Port** : `5432`
**Conteneur Docker** : `ptitspas-postgres`
## Schéma de la base de données
### Types ENUM
La base de données utilise plusieurs types énumérés PostgreSQL :
| Type ENUM | Valeurs possibles | Usage |
|-----------|------------------|-------|
| `role_type` | `parent`, `gestionnaire`, `super_admin`, `assistante_maternelle`, `administrateur` | Rôles des utilisateurs |
| `genre_type` | `H`, `F`, `Autre` | Genre des utilisateurs et enfants |
| `statut_utilisateur_type` | `en_attente`, `actif`, `suspendu` | Statut du compte utilisateur |
| `statut_enfant_type` | `a_naitre`, `actif`, `scolarise` | Statut de l'enfant |
| `statut_dossier_type` | `envoye`, `accepte`, `refuse` | Statut de la candidature |
| `statut_contrat_type` | `brouillon`, `en_attente_signature`, `valide`, `resilie` | Statut du contrat |
| `statut_avenant_type` | `propose`, `accepte`, `refuse` | Statut des avenants au contrat |
| `type_evenement_type` | `absence_enfant`, `conge_am`, `conge_parent`, `arret_maladie_am`, `evenement_rpe` | Type d'événement |
| `statut_evenement_type` | `propose`, `valide`, `refuse` | Statut de l'événement |
| `statut_validation_type` | `en_attente`, `valide`, `refuse` | Statut de validation générique |
---
## Tables
### 1. `utilisateurs`
Table centrale pour tous les types d'utilisateurs.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `email` | VARCHAR(255) | NOT NULL, UNIQUE | Email (avec validation regex) |
| `password` | TEXT | NOT NULL | Mot de passe hashé (bcrypt) |
| `prenom` | VARCHAR(100) | | Prénom |
| `nom` | VARCHAR(100) | | Nom de famille |
| `genre` | genre_type | | Genre de l'utilisateur |
| `role` | role_type | NOT NULL | Rôle de l'utilisateur |
| `statut` | statut_utilisateur_type | DEFAULT 'en_attente' | Statut du compte |
| `telephone` | VARCHAR(20) | | Téléphone principal |
| `adresse` | TEXT | | Adresse complète |
| `photo_url` | TEXT | | URL de la photo de profil |
| `consentement_photo` | BOOLEAN | DEFAULT false | Consentement photo |
| `date_consentement_photo` | TIMESTAMPTZ | | Date du consentement |
| `changement_mdp_obligatoire` | BOOLEAN | DEFAULT false | Force changement de MDP |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date de création |
| `modifie_le` | TIMESTAMPTZ | DEFAULT now() | Dernière modification |
| `ville` | VARCHAR(150) | | Ville |
| `code_postal` | VARCHAR(10) | | Code postal |
| `mobile` | VARCHAR(20) | | Téléphone mobile |
| `telephone_fixe` | VARCHAR(20) | | Téléphone fixe |
| `profession` | VARCHAR(150) | | Profession |
| `situation_familiale` | VARCHAR(50) | | Situation familiale |
| `date_naissance` | DATE | | Date de naissance |
**Contraintes** :
- Email validé par regex : `^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$`
---
### 2. `assistantes_maternelles`
Extension de la table `utilisateurs` pour les assistantes maternelles.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id_utilisateur` | UUID | PRIMARY KEY, FK → utilisateurs(id) | Référence à l'utilisateur |
| `numero_agrement` | VARCHAR(50) | | Numéro d'agrément |
| `nir_chiffre` | CHAR(15) | | NIR (Sécurité sociale) |
| `nb_max_enfants` | INT | | Capacité maximale d'accueil |
| `biographie` | TEXT | | Présentation |
| `disponible` | BOOLEAN | DEFAULT true | Disponibilité |
| `ville_residence` | VARCHAR(100) | | Ville de résidence |
| `date_agrement` | DATE | | Date d'obtention de l'agrément |
| `annee_experience` | SMALLINT | | Années d'expérience |
| `specialite` | VARCHAR(100) | | Spécialités |
| `place_disponible` | INT | | Nombre de places disponibles |
**Cascade** : `ON DELETE CASCADE` (suppression si utilisateur supprimé)
---
### 3. `parents`
Extension de la table `utilisateurs` pour les parents.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id_utilisateur` | UUID | PRIMARY KEY, FK → utilisateurs(id) | Référence à l'utilisateur |
| `id_co_parent` | UUID | FK → utilisateurs(id) | Référence au co-parent (optionnel) |
**Cascade** : `ON DELETE CASCADE`
---
### 4. `enfants`
Table des enfants pris en charge.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `statut` | statut_enfant_type | | Statut de l'enfant |
| `prenom` | VARCHAR(100) | | Prénom |
| `nom` | VARCHAR(100) | | Nom |
| `genre` | genre_type | | Genre |
| `date_naissance` | DATE | | Date de naissance |
| `date_prevue_naissance` | DATE | | Date prévue (si à naître) |
| `photo_url` | TEXT | | URL de la photo |
| `consentement_photo` | BOOLEAN | DEFAULT false | Consentement photo |
| `date_consentement_photo` | TIMESTAMPTZ | | Date du consentement |
| `est_multiple` | BOOLEAN | DEFAULT false | Indique si grossesse multiple |
---
### 5. `enfants_parents`
Table de liaison entre enfants et parents (relation N:N).
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id_parent` | UUID | FK → parents(id_utilisateur) | Référence au parent |
| `id_enfant` | UUID | FK → enfants(id) | Référence à l'enfant |
**Clé primaire composite** : `(id_parent, id_enfant)`
**Cascade** : `ON DELETE CASCADE`
---
### 6. `dossiers`
Dossiers de candidature des parents pour une assistante maternelle.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `id_parent` | UUID | FK → parents(id_utilisateur) | Parent demandeur |
| `id_enfant` | UUID | FK → enfants(id) | Enfant concerné |
| `presentation` | TEXT | | Présentation de la demande |
| `type_contrat` | VARCHAR(50) | | Type de contrat souhaité |
| `repas` | BOOLEAN | DEFAULT false | Demande de repas |
| `budget` | NUMERIC(10,2) | | Budget disponible |
| `planning_souhaite` | JSONB | | Planning souhaité (format JSON) |
| `statut` | statut_dossier_type | DEFAULT 'envoye' | Statut du dossier |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date de création |
| `modifie_le` | TIMESTAMPTZ | DEFAULT now() | Dernière modification |
**Cascade** : `ON DELETE CASCADE`
---
### 7. `messages`
Messages échangés dans le cadre d'un dossier.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `id_dossier` | UUID | FK → dossiers(id) | Dossier lié |
| `id_expediteur` | UUID | FK → utilisateurs(id) | Expéditeur |
| `contenu` | TEXT | | Contenu du message |
| `re_redige_par_ia` | BOOLEAN | DEFAULT false | Message réécrit par IA |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date d'envoi |
**Cascade** : `ON DELETE CASCADE`
---
### 8. `contrats`
Contrats conclus entre parents et assistantes maternelles.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `id_dossier` | UUID | UNIQUE, FK → dossiers(id) | Dossier source (1:1) |
| `planning` | JSONB | | Planning défini (format JSON) |
| `tarif_horaire` | NUMERIC(6,2) | | Tarif horaire |
| `indemnites_repas` | NUMERIC(6,2) | | Indemnités repas |
| `date_debut` | DATE | | Date de début du contrat |
| `statut` | statut_contrat_type | DEFAULT 'brouillon' | Statut du contrat |
| `signe_parent` | BOOLEAN | DEFAULT false | Signature parent |
| `signe_am` | BOOLEAN | DEFAULT false | Signature assistante maternelle |
| `finalise_le` | TIMESTAMPTZ | | Date de finalisation |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date de création |
| `modifie_le` | TIMESTAMPTZ | DEFAULT now() | Dernière modification |
**Cascade** : `ON DELETE CASCADE`
---
### 9. `avenants_contrats`
Modifications apportées aux contrats existants.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `id_contrat` | UUID | FK → contrats(id) | Contrat modifié |
| `modifications` | JSONB | | Détails des modifications (JSON) |
| `initie_par` | UUID | FK → utilisateurs(id) | Utilisateur initiateur |
| `statut` | statut_avenant_type | DEFAULT 'propose' | Statut de l'avenant |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date de création |
| `modifie_le` | TIMESTAMPTZ | DEFAULT now() | Dernière modification |
**Cascade** : `ON DELETE CASCADE`
---
### 10. `evenements`
Événements liés au planning (absences, congés, etc.).
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `type` | type_evenement_type | | Type d'événement |
| `id_enfant` | UUID | FK → enfants(id) | Enfant concerné |
| `id_am` | UUID | FK → utilisateurs(id) | Assistante maternelle |
| `id_parent` | UUID | FK → parents(id_utilisateur) | Parent |
| `cree_par` | UUID | FK → utilisateurs(id) | Créateur de l'événement |
| `date_debut` | TIMESTAMPTZ | | Date de début |
| `date_fin` | TIMESTAMPTZ | | Date de fin |
| `commentaires` | TEXT | | Commentaires |
| `statut` | statut_evenement_type | DEFAULT 'propose' | Statut de l'événement |
| `delai_grace` | TIMESTAMPTZ | | Délai de grâce |
| `urgent` | BOOLEAN | DEFAULT false | Événement urgent |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date de création |
| `modifie_le` | TIMESTAMPTZ | DEFAULT now() | Dernière modification |
**Cascade** : `ON DELETE CASCADE`
---
### 11. `signalements_bugs`
Signalements de bugs par les utilisateurs.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `id_utilisateur` | UUID | FK → utilisateurs(id) | Utilisateur signalant |
| `description` | TEXT | | Description du bug |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date du signalement |
---
### 12. `uploads`
Fichiers téléversés par les utilisateurs.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `id_utilisateur` | UUID | FK → utilisateurs(id), ON DELETE SET NULL | Utilisateur |
| `fichier_url` | TEXT | NOT NULL | URL du fichier |
| `type` | VARCHAR(50) | | Type de fichier |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date d'upload |
---
### 13. `notifications`
Notifications envoyées aux utilisateurs.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `id_utilisateur` | UUID | FK → utilisateurs(id) | Destinataire |
| `contenu` | TEXT | | Contenu de la notification |
| `lu` | BOOLEAN | DEFAULT false | Statut de lecture |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date de création |
**Cascade** : `ON DELETE CASCADE`
---
### 14. `validations`
Validations génériques de données utilisateur.
| Colonne | Type | Contraintes | Description |
|---------|------|-------------|-------------|
| `id` | UUID | PRIMARY KEY | Identifiant unique |
| `id_utilisateur` | UUID | FK → utilisateurs(id) | Utilisateur à valider |
| `type` | VARCHAR(50) | | Type de validation |
| `statut` | statut_validation_type | DEFAULT 'en_attente' | Statut |
| `cree_le` | TIMESTAMPTZ | DEFAULT now() | Date de demande |
| `modifie_le` | TIMESTAMPTZ | DEFAULT now() | Dernière modification |
| `valide_par` | UUID | FK → utilisateurs(id) | Validateur |
| `commentaire` | TEXT | | Commentaire du validateur |
---
## Relations principales
```
utilisateurs (1) ──┬──> (1) assistantes_maternelles
├──> (1) parents
└──> (N) messages
parents (1) ───> (N) enfants_parents <─── (N) enfants
parents (1) ───> (N) dossiers <─── (1) enfants
dossiers (1) ───> (N) messages
dossiers (1) ───> (1) contrats
contrats (1) ───> (N) avenants_contrats
enfants (1) ───> (N) evenements
```
---
## Données initiales (SEED)
### Super Administrateur par défaut
**Email** : `admin@ptits-pas.fr`
**Mot de passe** : `4dm1n1strateur`
**Rôle** : `super_admin`
**Statut** : `actif`
> ⚠️ **Sécurité** : Le mot de passe est hashé avec bcrypt (`$2b$12$...`).
> Il est **impératif** de changer ce mot de passe en production.
---
## Migrations
Les migrations sont gérées manuellement via le fichier SQL :
**Fichier** : `/database/migrations/01_init.sql`
### Appliquer les migrations
```bash
# Depuis le conteneur backend
npx prisma migrate deploy
# Ou manuellement depuis psql
psql -U admin -d ptitpas_db -f /database/migrations/01_init.sql
```
---
## Accès à la base de données
### Via PgAdmin
**URL** : `https://app.ptits-pas.fr/pgadmin`
**Email** : `admin@ptits-pas.fr`
**Mot de passe** : `admin123`
**Configuration serveur** :
- Host : `ptitspas-postgres`
- Port : `5432`
- Database : `ptitpas_db`
- Username : `admin`
- Password : `admin123`
### Via terminal (Docker)
```bash
# Connexion au conteneur PostgreSQL
docker exec -it ptitspas-postgres psql -U admin -d ptitpas_db
# Lister les tables
\dt
# Voir le schéma d'une table
\d utilisateurs
# Quitter
\q
```
---
## Recommandations de sécurité
1.**Mots de passe hashés** avec bcrypt
2.**Validation email** via regex
3. ⚠️ **Changer les credentials par défaut en production**
4. ⚠️ **Créer un utilisateur read-only pour les analytics**
5. ⚠️ **Activer SSL/TLS pour les connexions PostgreSQL**
6.**Utiliser des UUID** plutôt que des identifiants séquentiels
---
## Maintenance
### Backup de la base
```bash
docker exec ptitspas-postgres pg_dump -U admin ptitpas_db > backup.sql
```
### Restauration
```bash
docker exec -i ptitspas-postgres psql -U admin ptitpas_db < backup.sql
```
### Vérifier la taille de la base
```sql
SELECT pg_size_pretty(pg_database_size('ptitpas_db'));
```
---
**Dernière mise à jour** : Novembre 2025