From b21ec4fec8f86b03483bb353dfe85db296831a1c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 28 Nov 2025 16:52:04 +0000 Subject: [PATCH 1/2] fix: add missing parent_id and level columns for subtasks support ROOT CAUSE: During phases 1-5, subtask support was added which requires parent_id and level columns in note_todos and global_todos tables. However, the auto-migrate script did not include this migration, causing 500 errors when the API tried to SELECT these non-existent columns. Changes: - scripts/auto-migrate.js: Added Migration 4 to create parent_id and level columns if they don't exist - config/database.js: Updated CREATE TABLE statements to include parent_id and level columns in the initial schema This fixes the 500 error on GET /api/notes that occurred because the code was trying to SELECT columns that didn't exist in production. The migration will run automatically on next Docker startup and add the missing columns without data loss. Fixes: "je n ai plus aucune note qui s affichent" - notes not displaying --- config/database.js | 4 ++++ scripts/auto-migrate.js | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) 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'); From 44c120e8530d034c1ed2c334f003c4e8dd994b95 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 28 Nov 2025 16:52:43 +0000 Subject: [PATCH 2/2] docs: update deployment instructions with root cause --- DEPLOY-INSTRUCTIONS.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) 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)