import { MongoClient } from 'mongodb'; import { execSync } from 'child_process'; import crypto from 'crypto'; const MONGO_URI = "mongodb+srv://admtracksteel:mongodb26@cluster0.a4xiilu.mongodb.net/ts_gpi"; const DB_NAME = "ts_gpi"; const DEFAULT_ORG_ID = "e47e6210-4879-4e5b-bf21-9285d2713123"; const client = new MongoClient(MONGO_URI); // Map Mongo _id -> Supabase UUID const idMap = new Map(); function getUUID(mongoId) { if (!mongoId) return null; const mid = mongoId.toString(); if (idMap.has(mid)) return idMap.get(mid); const newUuid = crypto.randomUUID(); idMap.set(mid, newUuid); return newUuid; } function sqlSafe(val) { if (val === null || val === undefined) return 'NULL'; if (val instanceof Date) return `'${val.toISOString()}'`; if (Array.isArray(val)) return `'{"${val.join('","')}"}'`; if (typeof val === 'object' && val.toString) { const s = val.toString(); return `'${s.replace(/'/g, "''")}'`; } if (typeof val === 'string') return `'${val.replace(/'/g, "''")}'`; return val; } async function run() { try { await client.connect(); console.log("🚀 Conectado ao MongoDB Atlas..."); const db = client.db(DB_NAME); // 1. Mapear Projetos primeiro const mongoProjects = await db.collection('projects').find().toArray(); console.log(`📦 Encontrados ${mongoProjects.length} projetos.`); let projectInserts = []; for (const p of mongoProjects) { const uuid = getUUID(p._id); projectInserts.push(`INSERT INTO gpi.projects (id, organization_id, name, client, start_date, end_date, environment, technician, weight_kg, status, created_at, updated_at) VALUES (${sqlSafe(uuid)}, ${sqlSafe(DEFAULT_ORG_ID)}, ${sqlSafe(p.name)}, ${sqlSafe(p.client)}, ${sqlSafe(p.startDate)}, ${sqlSafe(p.endDate)}, ${sqlSafe(p.environment)}, ${sqlSafe(p.technician)}, ${sqlSafe(p.weightKg)}, 'active', ${sqlSafe(p.createdAt)}, ${sqlSafe(p.updatedAt)});`); } // 2. Mapear Biblioteca de Tintas (Technical Data Sheets) const mongoTDS = await db.collection('technicaldatasheets').find().toArray(); console.log(`📚 Encontradas ${mongoTDS.length} fichas técnicas.`); let tdsInserts = []; for (const t of mongoTDS) { const uuid = getUUID(t._id); tdsInserts.push(`INSERT INTO gpi.technical_data_sheets (id, organization_id, name, manufacturer, manufacturer_code, type, min_stock, typical_application, solids_volume, mixing_ratio, yield_theoretical, wft_min, wft_max, dft_min, dft_max, reducer, mixing_ratio_weight, mixing_ratio_volume, dft_reference, yield_factor, dilution, notes, created_at, updated_at) VALUES (${sqlSafe(uuid)}, ${sqlSafe(DEFAULT_ORG_ID)}, ${sqlSafe(t.name)}, ${sqlSafe(t.manufacturer)}, ${sqlSafe(t.manufacturerCode)}, ${sqlSafe(t.type)}, ${sqlSafe(t.minStock)}, ${sqlSafe(t.typicalApplication)}, ${sqlSafe(t.solidsVolume)}, ${sqlSafe(t.mixingRatio)}, ${sqlSafe(t.yieldTheoretical)}, ${sqlSafe(t.wftMin)}, ${sqlSafe(t.wftMax)}, ${sqlSafe(t.dftMin)}, ${sqlSafe(t.dftMax)}, ${sqlSafe(t.reducer)}, ${sqlSafe(t.mixingRatioWeight)}, ${sqlSafe(t.mixingRatioVolume)}, ${sqlSafe(t.dftReference)}, ${sqlSafe(t.yieldFactor)}, ${sqlSafe(t.dilution)}, ${sqlSafe(t.notes)}, ${sqlSafe(t.createdAt)}, ${sqlSafe(t.updatedAt)});`); } // 3. Mapear Esquemas de Pintura const mongoSchemes = await db.collection('paintingschemes').find().toArray(); console.log(`🎨 Encontrados ${mongoSchemes.length} esquemas de pintura.`); let schemeInserts = []; for (const s of mongoSchemes) { const uuid = crypto.randomUUID(); const projectId = getUUID(s.projectId); schemeInserts.push(`INSERT INTO gpi.painting_schemes (id, organization_id, project_id, name, type, coat, solids_volume, yield_theoretical, eps_min, eps_max, dilution, manufacturer, color, paint_consumption, thinner_consumption, paint_id, thinner_id, color_hex, thinner_symbol, notes, created_at, updated_at) VALUES (${sqlSafe(uuid)}, ${sqlSafe(DEFAULT_ORG_ID)}, ${sqlSafe(projectId)}, ${sqlSafe(s.name)}, ${sqlSafe(s.type)}, ${sqlSafe(s.coat)}, ${sqlSafe(s.solidsVolume)}, ${sqlSafe(s.yieldTheoretical)}, ${sqlSafe(s.epsMin)}, ${sqlSafe(s.epsMax)}, ${sqlSafe(s.dilution)}, ${sqlSafe(s.manufacturer)}, ${sqlSafe(s.color)}, ${sqlSafe(s.paintConsumption)}, ${sqlSafe(s.thinnerConsumption)}, ${sqlSafe(s.paintId)}, ${sqlSafe(s.thinnerId)}, ${sqlSafe(s.colorHex)}, ${sqlSafe(s.thinnerSymbol)}, ${sqlSafe(s.notes)}, NOW(), NOW());`); } // 4. Mapear Peças (Parts) const mongoParts = await db.collection('parts').find().toArray(); console.log(`🧩 Encontradas ${mongoParts.length} peças.`); let partsInserts = []; for (const pt of mongoParts) { const uuid = getUUID(pt._id); const projectId = getUUID(pt.projectId); partsInserts.push(`INSERT INTO gpi.parts (id, organization_id, project_id, description, dimensions, weight, type, area, quantity, notes, created_at, updated_at) VALUES (${sqlSafe(uuid)}, ${sqlSafe(DEFAULT_ORG_ID)}, ${sqlSafe(projectId)}, ${sqlSafe(pt.description)}, ${sqlSafe(pt.dimensions)}, ${sqlSafe(pt.weight)}, ${sqlSafe(pt.type)}, ${sqlSafe(pt.area)}, ${sqlSafe(pt.quantity)}, ${sqlSafe(pt.notes)}, NOW(), NOW());`); } // Executar SQL const allSQL = [...projectInserts, ...tdsInserts, ...schemeInserts, ...partsInserts].join('\n'); console.log("💾 Executando SQL no Supabase..."); // Escrever para arquivo temporário const fs = await import('fs'); fs.writeFileSync('/tmp/bulk_migration.sql', allSQL); // Executar via docker execSync(`docker exec -i supabase-db-h0oggskgs0ws0sco8kc4s8ws psql -U supabase_admin -d postgres < /tmp/bulk_migration.sql`); console.log("✅ Migração Concluída com Sucesso!"); } catch (e) { console.error("❌ ERRO DURANTE MIGRAÇÃO:", e.message); } finally { await client.close(); } } run();