# 🗄️ 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

