diff --git a/DEPLOY-INSTRUCTIONS.md b/DEPLOY-INSTRUCTIONS.md index 34d3891..3e83af0 100644 --- a/DEPLOY-INSTRUCTIONS.md +++ b/DEPLOY-INSTRUCTIONS.md @@ -3,8 +3,13 @@ ## Problème actuel Erreur 500 sur `/api/notes` - Les notes ne s'affichent pas -## Cause -Les données booléennes dans PostgreSQL sont stockées en INTEGER (0/1) au lieu de BOOLEAN (TRUE/FALSE) +## Causes identifiées + +### 1. Colonnes manquantes (PRINCIPAL) +Les colonnes `parent_id` et `level` ajoutées pendant les phases 1-5 pour le support des subtasks n'existaient pas dans la base PostgreSQL de production. + +### 2. Types booléens incorrects (SECONDAIRE) +Les données booléennes migrées de SQLite sont stockées en INTEGER (0/1) au lieu de BOOLEAN (TRUE/FALSE). ## ✅ Solution AUTOMATIQUE (Recommandée) @@ -20,12 +25,17 @@ docker-compose up -d --build Le conteneur Docker va automatiquement: 1. Attendre que PostgreSQL soit prêt -2. Exécuter les migrations de schéma -3. **Corriger automatiquement les types booléens** ✨ +2. **Exécuter les migrations de schéma** ✨ + - Ajouter les colonnes `parent_id` et `level` pour les subtasks + - Ajouter tous les autres champs manquants +3. **Corriger automatiquement les types booléens** + - Convertir INTEGER → BOOLEAN pour les champs concernés 4. Démarrer le serveur C'est tout ! Les notes s'afficheront correctement après le redémarrage. +**Note:** Les migrations sont idempotentes et ne causeront aucune perte de données. + --- ## Solution manuelle (Si vous n'utilisez pas Docker) diff --git a/config/database.js b/config/database.js index f2b20a9..fdc4980 100644 --- a/config/database.js +++ b/config/database.js @@ -126,6 +126,8 @@ async function initDatabase() { completed BOOLEAN DEFAULT FALSE, priority BOOLEAN DEFAULT FALSE, position INTEGER DEFAULT 0, + parent_id INTEGER REFERENCES note_todos(id) ON DELETE CASCADE, + level INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, completed_at TIMESTAMP ) @@ -140,6 +142,8 @@ async function initDatabase() { completed BOOLEAN DEFAULT FALSE, priority BOOLEAN DEFAULT FALSE, in_progress INTEGER DEFAULT 0, + parent_id INTEGER REFERENCES global_todos(id) ON DELETE CASCADE, + level INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, completed_at TIMESTAMP ) diff --git a/scripts/auto-migrate.js b/scripts/auto-migrate.js index ab25009..df91505 100644 --- a/scripts/auto-migrate.js +++ b/scripts/auto-migrate.js @@ -185,6 +185,55 @@ async function autoMigrate() { await client.query(`CREATE INDEX IF NOT EXISTS idx_global_todos_priority ON global_todos(priority DESC, created_at DESC)`); await client.query(`CREATE INDEX IF NOT EXISTS idx_note_todos_priority ON note_todos(priority DESC, position)`); + // Migration 4: Support des subtasks (parent_id, level) + logger.info(' Vérification: support des subtasks (parent_id, level)...'); + + const noteTodosParentIdExists = await client.query(` + SELECT column_name + FROM information_schema.columns + WHERE table_name='note_todos' AND column_name='parent_id' + `); + + if (noteTodosParentIdExists.rows.length === 0) { + logger.info(' → Ajout du champ parent_id à note_todos'); + await client.query(`ALTER TABLE note_todos ADD COLUMN parent_id INTEGER REFERENCES note_todos(id) ON DELETE CASCADE`); + await client.query(`CREATE INDEX IF NOT EXISTS idx_note_todos_parent_id ON note_todos(parent_id)`); + } + + const noteTodosLevelExists = await client.query(` + SELECT column_name + FROM information_schema.columns + WHERE table_name='note_todos' AND column_name='level' + `); + + if (noteTodosLevelExists.rows.length === 0) { + logger.info(' → Ajout du champ level à note_todos'); + await client.query(`ALTER TABLE note_todos ADD COLUMN level INTEGER DEFAULT 0`); + } + + const globalTodosParentIdExists = await client.query(` + SELECT column_name + FROM information_schema.columns + WHERE table_name='global_todos' AND column_name='parent_id' + `); + + if (globalTodosParentIdExists.rows.length === 0) { + logger.info(' → Ajout du champ parent_id à global_todos'); + await client.query(`ALTER TABLE global_todos ADD COLUMN parent_id INTEGER REFERENCES global_todos(id) ON DELETE CASCADE`); + await client.query(`CREATE INDEX IF NOT EXISTS idx_global_todos_parent_id ON global_todos(parent_id)`); + } + + const globalTodosLevelExists = await client.query(` + SELECT column_name + FROM information_schema.columns + WHERE table_name='global_todos' AND column_name='level' + `); + + if (globalTodosLevelExists.rows.length === 0) { + logger.info(' → Ajout du champ level à global_todos'); + await client.query(`ALTER TABLE global_todos ADD COLUMN level INTEGER DEFAULT 0`); + } + await client.query('COMMIT'); logger.info('✅ Migrations automatiques terminées avec succès');