147 lines
5.4 KiB
JavaScript
147 lines
5.4 KiB
JavaScript
/**
|
|
* 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);
|
|
});
|