Finalizando migração de dados do MongoDB Atlas para Supabase: corrigindo esquemas de campos decimais e garantindo integridade de relacionamento de projetos

This commit is contained in:
2026-04-03 18:15:32 +00:00
parent 5c24783320
commit dd06fd1196
3 changed files with 137 additions and 36 deletions

View File

@@ -66,15 +66,15 @@ CREATE TABLE IF NOT EXISTS gpi.painting_schemes (
name TEXT NOT NULL,
type TEXT,
coat TEXT,
solids_volume DECIMAL(5,2),
yield_theoretical DECIMAL(10,2),
eps_min DECIMAL(5,2),
eps_max DECIMAL(5,2),
dilution DECIMAL(5,2),
solids_volume DECIMAL(12,3),
yield_theoretical DECIMAL(12,3),
eps_min DECIMAL(12,3),
eps_max DECIMAL(12,3),
dilution DECIMAL(12,3),
manufacturer TEXT,
color TEXT,
paint_consumption DECIMAL(10,3),
thinner_consumption DECIMAL(10,3),
paint_consumption DECIMAL(12,3),
thinner_consumption DECIMAL(12,3),
paint_id TEXT,
thinner_id TEXT,
color_hex TEXT,
@@ -148,23 +148,23 @@ CREATE TABLE IF NOT EXISTS gpi.technical_data_sheets (
type TEXT,
file_url TEXT,
upload_date DATE,
solids_volume DECIMAL(5,2),
density DECIMAL(6,3),
solids_volume DECIMAL(12,3),
density DECIMAL(12,3),
mixing_ratio TEXT,
yield_theoretical DECIMAL(10,2),
wft_min DECIMAL(6,2),
wft_max DECIMAL(6,2),
dft_min DECIMAL(6,2),
dft_max DECIMAL(6,2),
yield_theoretical DECIMAL(12,3),
wft_min DECIMAL(12,3),
wft_max DECIMAL(12,3),
dft_min DECIMAL(12,3),
dft_max DECIMAL(12,3),
reducer TEXT,
mixing_ratio_weight TEXT,
mixing_ratio_volume TEXT,
dft_reference DECIMAL(6,2),
yield_factor DECIMAL(5,3),
dilution DECIMAL(5,2),
dft_reference DECIMAL(12,3),
yield_factor DECIMAL(12,3),
dilution DECIMAL(12,3),
notes TEXT,
manufacturer_code TEXT,
min_stock DECIMAL(10,3),
min_stock DECIMAL(12,3),
typical_application TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()

101
migrate.js Normal file
View File

@@ -0,0 +1,101 @@
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();

View File

@@ -65,15 +65,15 @@ CREATE TABLE IF NOT EXISTS gpi.painting_schemes (
name TEXT NOT NULL,
type TEXT,
coat TEXT,
solids_volume DECIMAL(5,2),
yield_theoretical DECIMAL(10,2),
eps_min DECIMAL(5,2),
eps_max DECIMAL(5,2),
dilution DECIMAL(5,2),
solids_volume DECIMAL(12,3),
yield_theoretical DECIMAL(12,3),
eps_min DECIMAL(12,3),
eps_max DECIMAL(12,3),
dilution DECIMAL(12,3),
manufacturer TEXT,
color TEXT,
paint_consumption DECIMAL(10,3),
thinner_consumption DECIMAL(10,3),
paint_consumption DECIMAL(12,3),
thinner_consumption DECIMAL(12,3),
paint_id TEXT,
thinner_id TEXT,
color_hex TEXT,
@@ -147,23 +147,23 @@ CREATE TABLE IF NOT EXISTS gpi.technical_data_sheets (
type TEXT,
file_url TEXT,
upload_date DATE,
solids_volume DECIMAL(5,2),
density DECIMAL(6,3),
solids_volume DECIMAL(12,3),
density DECIMAL(12,3),
mixing_ratio TEXT,
yield_theoretical DECIMAL(10,2),
wft_min DECIMAL(6,2),
wft_max DECIMAL(6,2),
dft_min DECIMAL(6,2),
dft_max DECIMAL(6,2),
yield_theoretical DECIMAL(12,3),
wft_min DECIMAL(12,3),
wft_max DECIMAL(12,3),
dft_min DECIMAL(12,3),
dft_max DECIMAL(12,3),
reducer TEXT,
mixing_ratio_weight TEXT,
mixing_ratio_volume TEXT,
dft_reference DECIMAL(6,2),
yield_factor DECIMAL(5,3),
dilution DECIMAL(5,2),
dft_reference DECIMAL(12,3),
yield_factor DECIMAL(12,3),
dilution DECIMAL(12,3),
notes TEXT,
manufacturer_code TEXT,
min_stock DECIMAL(10,3),
min_stock DECIMAL(12,3),
typical_application TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()