diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 0000000..272e6a9 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,873 @@ +# 🌐 Documentation API + +## Vue d'ensemble + +L'API PtitsPas est une API REST construite avec **NestJS**. + +**URL de base** : `https://app.ptits-pas.fr/api/v1` +**Format** : JSON +**Authentication** : JWT Bearer Token + +--- + +## Authentication + +Toutes les routes (sauf `/auth/login`, `/auth/register`, `/auth/refresh`) nécessitent un token JWT dans le header : + +```http +Authorization: Bearer +``` + +### Tokens + +L'API utilise deux types de tokens : +- **Access Token** : Durée de vie courte, utilisé pour les requêtes API +- **Refresh Token** : Durée de vie longue, utilisé pour renouveler l'access token + +--- + +## Endpoints + +### 🔐 Authentification (`/auth`) + +#### POST `/auth/login` + +Connexion d'un utilisateur. + +**Public** : ✅ Oui + +**Request Body** : +```json +{ + "email": "admin@ptits-pas.fr", + "password": "4dm1n1strateur" +} +``` + +**Response** (200) : +```json +{ + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "user": { + "id": "uuid", + "email": "admin@ptits-pas.fr", + "role": "super_admin", + "prenom": "Admin", + "nom": "Système" + } +} +``` + +**Errors** : +- `401` : Email ou mot de passe incorrect +- `403` : Compte suspendu ou en attente de validation + +--- + +#### POST `/auth/register` + +Inscription d'un nouvel utilisateur (parent ou assistante maternelle). + +**Public** : ✅ Oui + +**Request Body** : +```json +{ + "email": "parent@example.com", + "password": "motdepasse123", + "prenom": "Jean", + "nom": "Dupont", + "role": "parent", + "telephone": "0601020304" +} +``` + +**Response** (201) : +```json +{ + "message": "Inscription réussie. Votre compte est en attente de validation.", + "userId": "uuid" +} +``` + +**Errors** : +- `409` : Email déjà utilisé +- `400` : Données invalides + +--- + +#### POST `/auth/refresh` + +Rafraîchir l'access token à l'aide du refresh token. + +**Public** : ✅ Oui + +**Request Body** : +```json +{ + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} +``` + +**Response** (200) : +```json +{ + "access_token": "nouveau_token...", + "refresh_token": "nouveau_refresh_token..." +} +``` + +**Errors** : +- `401` : Token de rafraîchissement invalide ou expiré + +--- + +#### GET `/auth/me` + +Récupérer le profil de l'utilisateur connecté. + +**Auth** : 🔒 Requis + +**Response** (200) : +```json +{ + "id": "uuid", + "email": "admin@ptits-pas.fr", + "role": "super_admin", + "prenom": "Admin", + "nom": "Système", + "statut": "actif" +} +``` + +--- + +#### POST `/auth/logout` + +Déconnexion (invalide le refresh token). + +**Auth** : 🔒 Requis + +**Response** (200) : +```json +{ + "message": "Déconnexion réussie" +} +``` + +--- + +### 👥 Utilisateurs (`/users`) + +**Auth** : 🔒 Requis pour toutes les routes + +#### GET `/users` + +Liste tous les utilisateurs. + +**Rôles autorisés** : `super_admin` + +**Response** (200) : +```json +[ + { + "id": "uuid", + "email": "user@example.com", + "role": "parent", + "prenom": "Jean", + "nom": "Dupont", + "statut": "actif", + "cree_le": "2025-01-15T10:30:00Z" + } +] +``` + +--- + +#### GET `/users/:id` + +Récupérer un utilisateur par son ID. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Response** (200) : +```json +{ + "id": "uuid", + "email": "user@example.com", + "role": "parent", + "prenom": "Jean", + "nom": "Dupont", + "telephone": "0601020304", + "statut": "actif" +} +``` + +**Errors** : +- `404` : Utilisateur non trouvé +- `403` : Accès refusé + +--- + +#### POST `/users` + +Créer un nouvel utilisateur. + +**Rôles autorisés** : `super_admin` + +**Request Body** : +```json +{ + "email": "newuser@example.com", + "password": "password123", + "role": "gestionnaire", + "prenom": "Marie", + "nom": "Martin" +} +``` + +**Response** (201) : +```json +{ + "id": "uuid", + "email": "newuser@example.com", + "role": "gestionnaire" +} +``` + +--- + +#### PATCH `/users/:id` + +Mettre à jour un utilisateur. + +**Rôles autorisés** : `super_admin` + +**Request Body** (tous les champs sont optionnels) : +```json +{ + "prenom": "Jean-Claude", + "telephone": "0612345678", + "adresse": "1 rue de la Paix, 75001 Paris" +} +``` + +**Response** (200) : +```json +{ + "id": "uuid", + "email": "user@example.com", + "prenom": "Jean-Claude", + "telephone": "0612345678" +} +``` + +--- + +#### PATCH `/users/:id/valider` + +Valider un compte utilisateur en attente. + +**Rôles autorisés** : `super_admin`, `gestionnaire`, `administrateur` + +**Request Body** : +```json +{ + "comment": "Compte validé après vérification des documents" +} +``` + +**Response** (200) : +```json +{ + "message": "Compte validé avec succès", + "userId": "uuid" +} +``` + +--- + +#### PATCH `/users/:id/suspendre` + +Suspendre un compte utilisateur. + +**Rôles autorisés** : `super_admin`, `gestionnaire`, `administrateur` + +**Request Body** : +```json +{ + "comment": "Compte suspendu pour non-respect des conditions" +} +``` + +**Response** (200) : +```json +{ + "message": "Compte suspendu", + "userId": "uuid" +} +``` + +--- + +#### DELETE `/users/:id` + +Supprimer un utilisateur. + +**Rôles autorisés** : `super_admin` + +**Response** (200) : +```json +{ + "message": "Utilisateur supprimé" +} +``` + +--- + +### 🏢 Gestionnaires (`/gestionnaires`) + +**Auth** : 🔒 Requis pour toutes les routes + +#### GET `/gestionnaires` + +Liste tous les gestionnaires. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Response** (200) : +```json +[ + { + "id": "uuid", + "email": "gestionnaire@ptits-pas.fr", + "role": "gestionnaire", + "prenom": "Sophie", + "nom": "Leroy" + } +] +``` + +--- + +#### GET `/gestionnaires/:id` + +Récupérer un gestionnaire par son ID. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Response** (200) : Identique à `/users/:id` + +--- + +#### POST `/gestionnaires` + +Créer un nouveau gestionnaire. + +**Rôles autorisés** : `super_admin` + +**Request Body** : +```json +{ + "email": "nouveau.gestionnaire@ptits-pas.fr", + "password": "password123", + "prenom": "Laurent", + "nom": "Bernard" +} +``` + +**Response** (201) : +```json +{ + "id": "uuid", + "email": "nouveau.gestionnaire@ptits-pas.fr", + "role": "gestionnaire" +} +``` + +--- + +#### PATCH `/gestionnaires/:id` + +Mettre à jour un gestionnaire. + +**Rôles autorisés** : `super_admin` + +**Request Body** : Identique à `/users/:id` (PATCH) + +--- + +### 👶 Parents (`/parents`) + +**Auth** : 🔒 Requis pour toutes les routes + +#### GET `/parents` + +Liste tous les parents. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Response** (200) : +```json +[ + { + "id_utilisateur": "uuid", + "id_co_parent": "uuid", + "utilisateur": { + "email": "parent@example.com", + "prenom": "Jean", + "nom": "Dupont" + } + } +] +``` + +--- + +#### GET `/parents/:id` + +Récupérer un parent par son ID utilisateur. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Response** (200) : +```json +{ + "id_utilisateur": "uuid", + "id_co_parent": "uuid", + "utilisateur": { + "email": "parent@example.com", + "prenom": "Jean", + "nom": "Dupont", + "telephone": "0601020304" + } +} +``` + +--- + +#### POST `/parents` + +Créer un nouveau parent. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Request Body** : +```json +{ + "email": "parent@example.com", + "password": "password123", + "prenom": "Jean", + "nom": "Dupont", + "telephone": "0601020304", + "id_co_parent": "uuid" // optionnel +} +``` + +**Response** (201) : Identique à GET + +--- + +#### PATCH `/parents/:id` + +Mettre à jour un parent. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Request Body** : +```json +{ + "id_co_parent": "uuid", + "telephone": "0612345678" +} +``` + +--- + +### 👧 Enfants (`/enfants`) + +**Auth** : 🔒 Requis pour toutes les routes + +#### GET `/enfants` + +Liste tous les enfants. + +**Rôles autorisés** : `super_admin`, `gestionnaire`, `administrateur` + +**Response** (200) : +```json +[ + { + "id": "uuid", + "prenom": "Alice", + "nom": "Dupont", + "genre": "F", + "date_naissance": "2020-05-15", + "statut": "actif" + } +] +``` + +--- + +#### GET `/enfants/:id` + +Récupérer un enfant par son ID. + +**Rôles autorisés** : `super_admin`, `gestionnaire`, `administrateur`, `parent` (si c'est son enfant) + +**Response** (200) : +```json +{ + "id": "uuid", + "prenom": "Alice", + "nom": "Dupont", + "genre": "F", + "date_naissance": "2020-05-15", + "statut": "actif", + "consentement_photo": false +} +``` + +--- + +#### POST `/enfants` + +Créer un nouvel enfant. + +**Rôles autorisés** : `parent` + +**Request Body** : +```json +{ + "prenom": "Alice", + "nom": "Dupont", + "genre": "F", + "date_naissance": "2020-05-15", + "statut": "actif" +} +``` + +**Response** (201) : Identique à GET + +--- + +#### PATCH `/enfants/:id` + +Mettre à jour un enfant. + +**Rôles autorisés** : `super_admin`, `administrateur`, `parent` (si c'est son enfant) + +**Request Body** : +```json +{ + "statut": "scolarise", + "consentement_photo": true +} +``` + +--- + +#### DELETE `/enfants/:id` + +Supprimer un enfant. + +**Rôles autorisés** : `super_admin` + +**Response** (200) : +```json +{ + "message": "Enfant supprimé" +} +``` + +--- + +### 👩‍🍼 Assistantes Maternelles (`/assistantes-maternelles`) + +**Auth** : 🔒 Requis pour toutes les routes + +#### GET `/assistantes-maternelles` + +Liste toutes les assistantes maternelles. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Response** (200) : +```json +[ + { + "id_utilisateur": "uuid", + "numero_agrement": "AM123456", + "nb_max_enfants": 4, + "place_disponible": 2, + "disponible": true, + "utilisateur": { + "email": "am@example.com", + "prenom": "Marie", + "nom": "Martin" + } + } +] +``` + +--- + +#### GET `/assistantes-maternelles/:id` + +Récupérer une assistante maternelle par son ID utilisateur. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Response** (200) : +```json +{ + "id_utilisateur": "uuid", + "numero_agrement": "AM123456", + "nir_chiffre": "123456789012345", + "nb_max_enfants": 4, + "place_disponible": 2, + "biographie": "Assistante maternelle depuis 10 ans...", + "disponible": true, + "ville_residence": "Paris", + "date_agrement": "2015-06-01", + "annee_experience": 10, + "specialite": "Pédagogie Montessori" +} +``` + +--- + +#### POST `/assistantes-maternelles` + +Créer une nouvelle assistante maternelle. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Request Body** : +```json +{ + "email": "am@example.com", + "password": "password123", + "prenom": "Marie", + "nom": "Martin", + "numero_agrement": "AM123456", + "nb_max_enfants": 4, + "ville_residence": "Paris" +} +``` + +**Response** (201) : Identique à GET + +--- + +#### PATCH `/assistantes-maternelles/:id` + +Mettre à jour une assistante maternelle. + +**Rôles autorisés** : `super_admin`, `gestionnaire` + +**Request Body** : +```json +{ + "place_disponible": 1, + "disponible": true, + "biographie": "Nouvelle bio..." +} +``` + +--- + +#### DELETE `/assistantes-maternelles/:id` + +Supprimer une assistante maternelle. + +**Rôles autorisés** : `super_admin`, `gestionnaire`, `administrateur` + +**Response** (200) : +```json +{ + "message": "Assistante maternelle supprimée" +} +``` + +--- + +### 🏠 Root (`/`) + +#### GET `/` + +Aperçu de l'API. + +**Public** : ✅ Oui + +**Response** (200) : +```json +{ + "message": "Bienvenue sur l'API PtitsPas", + "version": "1.0.0", + "endpoints": { + "auth": "/api/v1/auth", + "users": "/api/v1/users", + "parents": "/api/v1/parents", + "enfants": "/api/v1/enfants", + "assistantes-maternelles": "/api/v1/assistantes-maternelles", + "gestionnaires": "/api/v1/gestionnaires" + } +} +``` + +--- + +#### GET `/hello` + +Endpoint de test. + +**Public** : ✅ Oui + +**Response** (200) : +```text +Hello World! +``` + +--- + +## Codes d'erreur HTTP + +| Code | Signification | Explication | +|------|---------------|-------------| +| `200` | OK | Requête réussie | +| `201` | Created | Ressource créée | +| `400` | Bad Request | Données invalides | +| `401` | Unauthorized | Non authentifié ou token invalide | +| `403` | Forbidden | Accès refusé (rôle insuffisant) | +| `404` | Not Found | Ressource non trouvée | +| `409` | Conflict | Conflit (ex: email déjà existant) | +| `500` | Internal Server Error | Erreur serveur | + +--- + +## Format des réponses d'erreur + +```json +{ + "statusCode": 400, + "message": "Validation failed", + "error": "Bad Request" +} +``` + +Ou avec détails : + +```json +{ + "statusCode": 403, + "message": "Accès refusé : rôle insuffisant", + "error": "Forbidden" +} +``` + +--- + +## Authentification et Rôles + +### Hiérarchie des rôles + +1. **super_admin** : Accès total +2. **administrateur** : Gestion des utilisateurs +3. **gestionnaire** : Gestion des dossiers et validation +4. **assistante_maternelle** : Accès à ses propres données +5. **parent** : Accès à ses propres données et enfants + +### Guards + +L'API utilise deux guards : +- **AuthGuard** : Vérifie la validité du token JWT +- **RolesGuard** : Vérifie que l'utilisateur a le bon rôle + +### Décorateurs + +- `@Public()` : Route accessible sans authentification +- `@Roles(...roles)` : Restreint l'accès aux rôles spécifiés +- `@User()` : Injecte l'utilisateur connecté dans le contrôleur + +--- + +## Swagger / OpenAPI + +L'API expose automatiquement sa documentation Swagger : + +**URL** : `https://app.ptits-pas.fr/api/docs` + +Cette documentation interactive permet de : +- Visualiser tous les endpoints +- Tester les requêtes directement +- Voir les schémas de données + +--- + +## Exemples d'utilisation + +### Connexion et récupération du profil + +```bash +# 1. Login +curl -X POST https://app.ptits-pas.fr/api/v1/auth/login \ + -H "Content-Type: application/json" \ + -d '{"email":"admin@ptits-pas.fr","password":"4dm1n1strateur"}' + +# Response +{ + "access_token": "eyJhbGc...", + "refresh_token": "eyJhbGc..." +} + +# 2. Récupérer son profil +curl https://app.ptits-pas.fr/api/v1/auth/me \ + -H "Authorization: Bearer eyJhbGc..." +``` + +### Créer un parent + +```bash +curl -X POST https://app.ptits-pas.fr/api/v1/parents \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "email": "parent@example.com", + "password": "password123", + "prenom": "Jean", + "nom": "Dupont", + "telephone": "0601020304" + }' +``` + +--- + +## Limitations et Rate Limiting + +**Actuellement** : Aucune limitation n'est active. + +**À implémenter** : +- Rate limiting (ex: 100 requêtes/minute) +- Pagination pour les listes longues +- Filtrage et tri sur les endpoints de liste + +--- + +## Évolutions prévues + +- [ ] Endpoints pour les dossiers (`/dossiers`) +- [ ] Endpoints pour les contrats (`/contrats`) +- [ ] Endpoints pour les événements (`/evenements`) +- [ ] Endpoints pour les messages (`/messages`) +- [ ] Endpoints pour les notifications (`/notifications`) +- [ ] WebSocket pour les notifications en temps réel +- [ ] Upload de fichiers (`/uploads`) +- [ ] Génération de PDF (contrats) + +--- + +**Dernière mise à jour** : Novembre 2025 + diff --git a/docs/AUDIT.md b/docs/AUDIT.md new file mode 100644 index 0000000..3b06086 --- /dev/null +++ b/docs/AUDIT.md @@ -0,0 +1,98 @@ +# 🕵️ Rapport d'Audit Technique & Fonctionnel - Projet P'titsPas (Ynov) + +**Date** : 23 Novembre 2025 +**Auditeur** : Assistant IA (Deploy Infra V2) +**Objet** : État des lieux avant reprise des développements pour finalisation. + +--- + +## 🚨 Synthèse Exécutive + +Le projet dispose d'une **base technique saine** (NestJS, PostgreSQL, Docker) et d'une structure de code propre. Cependant, **plusieurs fonctionnalités critiques du Cahier des Charges (CDC) sont manquantes ou incomplètes**, rendant l'application inutilisable en l'état pour le workflow principal (Inscription -> Validation -> Utilisation). + +**Score d'avancement estimé : 25%** +(Backend: 60%, Frontend: 10% [Coquille vide], Infra: 80%) + +--- + +## 1. 🏗️ Infrastructure & Docker + +### ✅ Points Positifs +* **Stack propre** : Architecture micro-services (Backend, Frontend, Database, PgAdmin). +* **Configuration Traefik** : Les labels et le routing (`ynov.ptits-pas.fr`) sont corrects. +* **Images optimisées** : Utilisation de builds multi-stage. + +### ⚠️ Problèmes & Correctifs +1. **Processus Zombies (Critique)** : + * **Constat** : Plus de 9000 processus zombies détectés. + * **Cause** : Le conteneur Backend lance `node` en PID 1 sans gestionnaire de signaux (`init`). + * **Action** : Ajouter `tini` ou `dumb-init` dans le `Dockerfile` Backend. +2. **Base de Données (Seed)** : + * **Constat** : Le script d'initialisation (`01_init.sql`) insère un administrateur avec le mot de passe `"admin123"` **en clair**. + * **Impact** : Impossible de se connecter (le Backend attend un hash Bcrypt). + * **Action** : Remplacer l'insertion SQL par un vrai hash ou un script de seed NestJS. + +--- + +## 2. 🔙 Backend (NestJS) + +### ✅ Points Positifs +* **Architecture** : Modulaire (Auth, User, Parents, Enfants...). +* **Qualité Code** : Typage fort, DTOs validés (`class-validator`), Entités TypeORM claires. + +### ❌ Écarts Fonctionnels Majeurs +| Fonctionnalité | État | Problème Identifié | +| :--- | :---: | :--- | +| **Envoi d'E-mails** | 🔴 **ABSENT** | Aucune librairie mail (Nodemailer) installée. Aucune logique d'envoi. | +| **Inscription** | 🟠 **Incomplet** | L'utilisateur est créé, mais sa fiche métier (`Parents` ou `AssistanteMaternelle`) **n'est pas générée**. Elle n'est créée qu'à la validation, ce qui empêche le remplissage du profil en amont. | +| **Validation Compte** | 🟠 **Partiel** | Le changement de statut fonctionne, mais **aucune notification mail** n'est envoyée (requis par CDC). | +| **Gestionnaire** | ✅ **OK** | La route de création par SuperAdmin existe et est sécurisée. | + +--- + +## 3. 📱 Frontend (Flutter) + +### ✅ Points Positifs +* Structure du projet cohérente. +* Authentification (Login) implémentée. + +### ❌ Écarts Fonctionnels Majeurs +| Écran / Fonction | État | Problème Identifié | +| :--- | :---: | :--- | +| **Création Gestionnaire** | 🔴 **VIDE** | Le fichier `gestionnaires_create.dart` contient uniquement un texte placeholder. **Aucun formulaire.** | +| **Dashboard Admin** | 🔴 **FAKE** | L'écran existe mais affiche des données simulées "en dur" (Mock). **Non connecté à l'API.** Impossible de valider les comptes. | +| **Dashboard Parent** | 🔴 **FAKE** | L'écran existe, architecture propre (Service/Controller), mais toutes les données (Enfants, Contrats) sont mockées (`TODO: API Call`). | +| **Dashboard AssMat** | 🔴 **INEXISTANT** | Aucun écran trouvé pour l'accueil des Assistantes Maternelles. | +| **Contact Support** | 🔴 **Fake** | Bouton présent mais code vide (`// TODO`). | +| **Signalement Bug** | 🔴 **Fake** | Idem, code non implémenté. | + +--- + +## 4. 📝 Plan d'Action Prioritaire (Roadmap de Réparation) + +Pour rendre l'application fonctionnelle selon le "Workflow attendu", voici les étapes techniques à réaliser dans l'ordre : + +### Étape 1 : Réparation Socle (Infra & Data) +1. **Fixer le Dockerfile Backend** (Tini pour les zombies). +2. **Fixer le mot de passe Admin** : Créer un script pour mettre à jour le hash du mot de passe `admin123` en base de données. + +### Étape 2 : Implémentation Backend (Mail & Workflow) +3. **Installer `nodemailer`** et configurer le service SMTP (via le serveur mail Host). +4. **Corriger `register`** : Créer l'entité `Parent`/`AssMat` dès l'inscription (vide mais existante). +5. **Corriger `validateUser`** : Ajouter l'envoi de mail de notification (Validé/Refusé). + +### Étape 3 : Implémentation Frontend (Écrans Manquants) +6. **Développer l'écran "Créer Gestionnaire"** : Formulaire (Nom, Prénom, Email, MDP) + Appel API. +7. **Vérifier/Finir le Dashboard Gestionnaire** : Liste des utilisateurs "En attente" + Boutons Valider/Refuser. + +### Étape 4 : Connexion (Workflow Complet) +8. Tester le cycle complet : + * Login SuperAdmin -> Création Gestionnaire. + * Login Gestionnaire -> Vue vide. + * Inscription Parent -> Apparition dans la liste Gestionnaire. + * Validation par Gestionnaire -> Mail reçu par Parent. + * Login Parent -> Accès autorisé. + +--- +*Ce document sert de référence pour la suite des travaux.* + diff --git a/docs/DATABASE.md b/docs/DATABASE.md new file mode 100644 index 0000000..1a95975 --- /dev/null +++ b/docs/DATABASE.md @@ -0,0 +1,421 @@ +# 🗄️ 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 + diff --git a/README-ARCHITECTURE.md b/docs/README-ARCHITECTURE.md similarity index 100% rename from README-ARCHITECTURE.md rename to docs/README-ARCHITECTURE.md diff --git a/README-DEPLOYMENT.md b/docs/README-DEPLOYMENT.md similarity index 100% rename from README-DEPLOYMENT.md rename to docs/README-DEPLOYMENT.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..0d05d77 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,53 @@ +# 📚 Documentation PtitsPas App + +Bienvenue dans la documentation complète de l'application PtitsPas. + +## 📖 Table des matières + +### Architecture & Infrastructure +- [**Architecture**](./README-ARCHITECTURE.md) - Vue d'ensemble de l'architecture mono-repo et multi-conteneurs +- [**Déploiement**](./README-DEPLOYMENT.md) - Guide complet de déploiement et configuration CI/CD + +### Développement +- [**API Documentation**](./API.md) - Documentation complète des endpoints REST +- [**Database Schema**](./DATABASE.md) - Schéma de la base de données et modèles +- [**Workflow de développement**](./WORKFLOW.md) - Process Git, branches et déploiement + +### Administration +- [**Guide d'administration**](./ADMIN.md) - Gestion des utilisateurs, accès PgAdmin, logs +- [**Troubleshooting**](./TROUBLESHOOTING.md) - Résolution des problèmes courants + +### Audit & Analyse +- [**Audit du projet YNOV**](./AUDIT.md) - Analyse complète du code étudiant et fonctionnalités + +### Frontend +- [**Frontend Flutter**](./FRONTEND.md) - Structure de l'application mobile/web + +## 🚀 Quick Start + +```bash +# Cloner le projet +git clone ssh://gitea-jmartin/jmartin/app.git ptitspas-app + +# Lancer l'environnement de développement +cd ptitspas-app +docker compose up -d + +# Accéder aux services +Frontend: https://app.ptits-pas.fr +API: https://app.ptits-pas.fr/api +PgAdmin: https://app.ptits-pas.fr/pgadmin +``` + +## 🔗 Liens utiles + +- **Gitea** : https://git.ptits-pas.fr +- **Production** : https://app.ptits-pas.fr +- **Mail** : https://mail.ptits-pas.fr + +## 📝 Maintenance + +Cette documentation est maintenue par Julien Martin (julien.martin@ptits-pas.fr). + +Dernière mise à jour : Novembre 2025 +