From 308906b328549f445da415f8f44cd570a62228b2 Mon Sep 17 00:00:00 2001 From: javier Date: Mon, 6 Jul 2026 16:32:00 +0200 Subject: [PATCH] =?UTF-8?q?fix(migrations):=20drop=20FK=20antes=20que=20?= =?UTF-8?q?=C3=ADndice=20al=20soltar=20phase=5Fid=20(MySQL)=20+=20idempote?= =?UTF-8?q?ncia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - El orden en up() era incorrecto para MySQL: intentaba dropear el índice inspection_templates_phase_id_index antes de la FK que lo sustentaba, dando "Cannot drop index: needed in a foreign key constraint (1553)". Corregido: primero dropForeign, después dropIndex, después dropColumn. - Creación del pivot ahora protegida con Schema::hasTable, para poder reintentar la migración si un fallo previo dejó la tabla creada pero la migración sin marcar como completa. Sin cambios funcionales; suite 91 verde (sqlite). Co-Authored-By: Claude Opus 4.7 --- ...inspection_templates_global_with_pivot.php | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/database/migrations/2026_06_25_120000_make_inspection_templates_global_with_pivot.php b/database/migrations/2026_06_25_120000_make_inspection_templates_global_with_pivot.php index 43f82bb..f4e7e08 100644 --- a/database/migrations/2026_06_25_120000_make_inspection_templates_global_with_pivot.php +++ b/database/migrations/2026_06_25_120000_make_inspection_templates_global_with_pivot.php @@ -15,14 +15,17 @@ return new class extends Migration */ public function up(): void { - // Pivot template ↔ project - Schema::create('inspection_template_project', function (Blueprint $table) { - $table->id(); - $table->foreignId('inspection_template_id')->constrained()->cascadeOnDelete(); - $table->foreignId('project_id')->constrained()->cascadeOnDelete(); - $table->timestamps(); - $table->unique(['inspection_template_id', 'project_id'], 'itp_template_project_unique'); - }); + // Pivot template ↔ project (idempotente: si el up() falló a mitad la primera + // vez, la tabla puede existir ya; en ese caso saltamos su creación). + if (! Schema::hasTable('inspection_template_project')) { + Schema::create('inspection_template_project', function (Blueprint $table) { + $table->id(); + $table->foreignId('inspection_template_id')->constrained()->cascadeOnDelete(); + $table->foreignId('project_id')->constrained()->cascadeOnDelete(); + $table->timestamps(); + $table->unique(['inspection_template_id', 'project_id'], 'itp_template_project_unique'); + }); + } // Migrar la asignación existente (project_id en inspection_templates → pivot) $rows = DB::table('inspection_templates')->whereNotNull('project_id')->get(['id', 'project_id']); @@ -37,12 +40,16 @@ return new class extends Migration ); } - // Drop columna phase_id (la asociación a fase deja de existir) + // Drop columna phase_id (la asociación a fase deja de existir). + // ORDEN IMPORTANTE en MySQL: primero FK, luego índice, luego columna. if (Schema::hasColumn('inspection_templates', 'phase_id')) { Schema::table('inspection_templates', function (Blueprint $table) { - // Algunos motores (SQLite) requieren dropear el índice antes de la columna. + // 1) FK primero: si no la dropeamos, MySQL rechaza soltar el índice + // que la sustenta ("needed in a foreign key constraint"). + try { $table->dropForeign(['phase_id']); } catch (\Throwable $e) { /* sqlite sin FKs / ya inexistente */ } + // 2) Índice después (nombre por convención de Laravel). try { $table->dropIndex('inspection_templates_phase_id_index'); } catch (\Throwable $e) { /* ya no existe */ } - try { $table->dropForeign(['phase_id']); } catch (\Throwable $e) { /* sqlite sin FKs */ } + // 3) Columna al final. $table->dropColumn('phase_id'); }); }