/** * SEED JSON - App RecolecciΓ³n Inteligente * Uso: npm run seed */ require('dotenv').config(); const { Pool } = require('pg'); const fs = require('fs'); const path = require('path'); const pool = new Pool({ host: process.env.DB_HOST || 'localhost', port: parseInt(process.env.DB_PORT || '5433'), database: process.env.DB_NAME || 'recoleccion_db', user: process.env.DB_USER || 'recoleccion', password: process.env.DB_PASSWORD || 'recoleccion123', }); function readJson(filename) { const filepath = path.join(__dirname, '..', 'data', filename); return JSON.parse(fs.readFileSync(filepath, 'utf-8')); } function parseHorario(str) { const match = str.match(/^(\w+)\s*\((\d{2}:\d{2})\s*-\s*(\d{2}:\d{2})\)/); if (!match) throw new Error(`Horario no reconocido: "${str}"`); return { turno: match[1], inicio: match[2], fin: match[3] }; } async function seed() { const client = await pool.connect(); try { await client.query('BEGIN'); const rutas = readJson('rutas.json'); const colonias = readJson('colonias-rutas.json'); console.log(`\nπŸ“¦ Sembrando ${rutas.length} rutas...`); for (const ruta of rutas) { const pos1 = ruta.positions.find(p => p.positionId === 1); const pos8 = ruta.positions.find(p => p.positionId === 8); const horaInicio = new Date(pos1.timestamp).toISOString().substring(11, 16); const horaFin = new Date(pos8.timestamp).toISOString().substring(11, 16); // ── Insertar ruta ────────────────────────────────────── const { rows: [rutaRow] } = await client.query( `INSERT INTO rutas (route_id, nombre, truck_id, hora_inicio, hora_fin_ref) VALUES ($1, $2, $3, $4::TIME, $5::TIME) ON CONFLICT (route_id) DO UPDATE SET nombre = EXCLUDED.nombre, truck_id = EXCLUDED.truck_id, hora_inicio = EXCLUDED.hora_inicio, hora_fin_ref = EXCLUDED.hora_fin_ref RETURNING id`, [ruta.routeId, ruta.name, ruta.truckId, horaInicio, horaFin] ); const rutaId = rutaRow.id; // ── Estado inicial ───────────────────────────────────── await client.query( `INSERT INTO estado_ruta (ruta_id, estado, position_id_actual) VALUES ($1, 'INACTIVA', 1) ON CONFLICT (ruta_id) DO NOTHING`, [rutaId] ); // ── Posiciones ───────────────────────────────────────── const tsBase = new Date(pos1.timestamp).getTime(); for (const pos of ruta.positions) { const offsetSeg = Math.round((new Date(pos.timestamp).getTime() - tsBase) / 1000); // IMPORTANTE: punto va al final ($8) para que los parΓ‘metros // sean estrictamente secuenciales $1..$8 sin saltos const wkt = `SRID=4326;POINT(${pos.lng} ${pos.lat})`; await client.query( `INSERT INTO ruta_posiciones (ruta_id, position_id, lat, lng, speed_kmh, ts_referencia, offset_seg, punto) VALUES ($1, $2, $3, $4, $5, $6::timestamptz,$7, $8::geography) ON CONFLICT (ruta_id, position_id) DO UPDATE SET lat = EXCLUDED.lat, lng = EXCLUDED.lng, speed_kmh = EXCLUDED.speed_kmh, ts_referencia = EXCLUDED.ts_referencia, offset_seg = EXCLUDED.offset_seg, punto = EXCLUDED.punto`, [rutaId, pos.positionId, pos.lat, pos.lng, pos.speed, pos.timestamp, offsetSeg, wkt] ); } console.log(` βœ“ ${ruta.routeId} β€” ${ruta.name}`); } // ── Colonias ─────────────────────────────────────────────── console.log(`\nπŸ—ΊοΈ Sembrando ${colonias.length} colonias...`); for (const col of colonias) { const { rows: [rutaRow] } = await client.query( 'SELECT id FROM rutas WHERE route_id = $1', [col.routeId] ); if (!rutaRow) { console.warn(` ⚠️ ${col.routeId} no encontrada para "${col.colonia}". Omitida.`); continue; } const h = parseHorario(col.horarioEstimado); await client.query( `INSERT INTO colonias (nombre, ruta_id, horario_turno, hora_inicio_est, hora_fin_est) VALUES ($1, $2, $3, $4::TIME, $5::TIME) ON CONFLICT (nombre) DO UPDATE SET ruta_id = EXCLUDED.ruta_id, horario_turno = EXCLUDED.horario_turno, hora_inicio_est = EXCLUDED.hora_inicio_est, hora_fin_est = EXCLUDED.hora_fin_est`, [col.colonia, rutaRow.id, h.turno, h.inicio, h.fin] ); console.log(` βœ“ ${col.colonia} β†’ ${col.routeId} (${h.turno} ${h.inicio}-${h.fin})`); } await client.query('COMMIT'); console.log('\nβœ… Seed completado exitosamente.\n'); } catch (err) { await client.query('ROLLBACK'); console.error('\n❌ Error en el seed, se hizo ROLLBACK:', err.message); throw err; } finally { client.release(); await pool.end(); } } seed().catch((err) => { console.error('πŸ’₯ Error fatal:', err.message); process.exit(1); });