const xlsx = require('xlsx'); const { Client } = require('pg'); const path = require('path'); const filePath = path.join(__dirname, '..', 'Consolidated_report_v2_with_feed-names (1).xlsx'); const client = new Client({ user: 'admin', host: 'localhost', database: 'sop_monitoring', password: 'password', port: 5432, }); function parseDuration(durationStr) { if (!durationStr) return 0; const hMatch = durationStr.match(/(\d+)h/); const mMatch = durationStr.match(/(\d+)m/); const sMatch = durationStr.match(/(\d+)s/); let seconds = 0; if (hMatch) seconds += parseInt(hMatch[1]) * 3600; if (mMatch) seconds += parseInt(mMatch[1]) * 60; if (sMatch) seconds += parseInt(sMatch[1]); return seconds; } function parseCellEvents(cellText, cameraZone, startTime, endTime, totalDuration) { if (!cellText) return []; const events = []; const blocks = cellText.split(/\r?\n---\r?\n/); for (const block of blocks) { const lines = block.split(/\r?\n/); if (lines.length === 0) continue; let eventDesc = lines[0]; let state = 'Active'; let stateDuration = totalDuration; if (lines.length > 1) { const stateMatch = lines[1].match(/(Active|Waste|Idle|Load waiting|Start point):\s*(.*)/i); if (stateMatch) { let stateText = stateMatch[1]; if (stateText.toLowerCase() === 'load waiting') state = 'Load waiting'; else if (stateText.toLowerCase() === 'waste') state = 'Waste'; else if (stateText.toLowerCase() === 'idle') state = 'Idle'; else if (stateText.toLowerCase() === 'start point') state = 'Active'; else state = 'Active'; if (stateText.toLowerCase() !== 'start point') { stateDuration = parseDuration(stateMatch[2]); } } } events.push({ start_time: startTime, end_time: endTime, duration_seconds: totalDuration, camera_zone: cameraZone, event_description: eventDesc.trim(), state, state_duration_seconds: stateDuration }); } return events; } async function run() { await client.connect(); // Create table if not exists (in case it wasn't created yet) await client.query('DROP TABLE IF EXISTS events;'); await client.query(` CREATE TABLE IF NOT EXISTS events ( id SERIAL PRIMARY KEY, changeover_id VARCHAR(100), changeover_date DATE, start_time TIME, end_time TIME, duration_seconds INTEGER, camera_zone VARCHAR(50), event_description TEXT, state VARCHAR(50), state_duration_seconds INTEGER ); `); await client.query('TRUNCATE TABLE events RESTART IDENTITY;'); const wb = xlsx.readFile(filePath); const sheet = wb.Sheets['Time Matrix']; const data = xlsx.utils.sheet_to_json(sheet, { header: 1, raw: false, dateNF: 'yyyy-mm-dd hh:mm:ss' }); // Start from row index 8 (skipping headers in the new file format) let allEvents = []; for (let i = 8; i < data.length; i++) { const row = data[i]; let startTime = row[1]; let endTime = row[2]; let durationStr = row[4]; if (!startTime || !endTime) continue; // Skip empty rows // Handle "0s / start marker" let totalDuration = row[3] ? parseInt(row[3]) : parseDuration(durationStr); // CO if (row[5]) allEvents.push(...parseCellEvents(row[5], 'CO', startTime, endTime, totalDuration)); // Mill if (row[6]) allEvents.push(...parseCellEvents(row[6], 'Mill', startTime, endTime, totalDuration)); // Conveyor if (row[7]) allEvents.push(...parseCellEvents(row[7], 'Conveyor', startTime, endTime, totalDuration)); } const changeoverId = 'CO-DEMO-1'; const changeoverDate = '2026-07-28'; for (const ev of allEvents) { try { await client.query( `INSERT INTO events (changeover_id, changeover_date, start_time, end_time, duration_seconds, camera_zone, event_description, state, state_duration_seconds) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`, [changeoverId, changeoverDate, ev.start_time, ev.end_time, ev.duration_seconds, ev.camera_zone, ev.event_description, ev.state, ev.state_duration_seconds] ); } catch(err) { console.error("Error inserting:", ev, err); } } console.log(`Inserted ${allEvents.length} events into the database.`); await client.end(); } run().catch(console.error);