diff --git a/server.js b/server.js index bd4a500..fb45b92 100644 --- a/server.js +++ b/server.js @@ -1,326 +1,6 @@ -require('dotenv').config(); -const express = require('express'); -const { Pool } = require('pg'); -const cors = require('cors'); - -const app = express(); -const port = process.env.PORT || 80; - -// Database Connection -const pool = new Pool({ - host: process.env.DB_HOST, - port: process.env.DB_PORT, - user: process.env.DB_USER, - password: process.env.DB_PASSWORD, - database: process.env.DB_NAME, - idleTimeoutMillis: 30000, - connectionTimeoutMillis: 2000, -}); - -pool.on('error', (err) => { - console.error('Unexpected error on idle client', err); -}); - -// Middleware -app.use(cors()); -app.use(express.json({ limit: '50mb' })); -app.use(express.static(__dirname)); - -// Helper to run the schema isolation command +// Schema-Helper async function setSchema(client) { - await client.query(`SET search_path TO ${process.env.DB_SCHEMA}, public;`); + await client.query(`SET search_path TO wind_projekt_bwscheddebrock, public;`); } - -// Routes -app.get('/api/health', (req, res) => { - res.json({ status: 'OK', time: new Date().toISOString() }); -}); - -// 1. Get Owner Data -app.get('/api/owners', async (req, res) => { - console.log("Anfrage erhalten: /api/owners"); - const client = await pool.connect(); - try { - await setSchema(client); - // 1. Log actual count in DB - const countRes = await client.query('SELECT count(*) FROM bw_scheddebrock."Eigentuemerdaten"'); - console.log(`Datenbank-Check: ${countRes.rows[0].count} Eigentümer in bw_scheddebrock."Eigentuemerdaten" gefunden.`); - - const query = ` - SELECT - *, - ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry - FROM bw_scheddebrock."Eigentuemerdaten" - `; - const result = await client.query(query); - console.log(`Abfrage erfolgreich: ${result.rowCount} Zeilen für Frontend geladen.`); - - const geojson = { - type: "FeatureCollection", - features: result.rows.map(row => { - const { geometry, geom, ...properties } = row; - const geomObj = typeof geometry === 'string' ? JSON.parse(geometry) : geometry; - return { - type: "Feature", - id: row.id || row.id_0, - geometry: geomObj, - properties: properties - }; - }) - }; - res.json(geojson); - } catch (err) { - console.error(err); - res.status(500).json({ error: 'Failed to fetch owner data' }); - } finally { - client.release(); - } -}); - -// 2. Get Usage Data (Nutzung) -app.get('/api/usage', async (req, res) => { - const client = await pool.connect(); - try { - await setSchema(client); - // 1. Log actual count in DB - const countRes = await client.query('SELECT count(*) FROM bw_scheddebrock."Nutzung"'); - console.log(`Datenbank-Check: ${countRes.rows[0].count} Nutzungs-Flächen in bw_scheddebrock."Nutzung" gefunden.`); - - const query = ` - SELECT - *, - ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry - FROM bw_scheddebrock."Nutzung" - `; - const result = await client.query(query); - console.log(`Abfrage erfolgreich: ${result.rowCount} Zeilen für Frontend geladen.`); - - const geojson = { - type: "FeatureCollection", - features: result.rows.map(row => { - const { geometry, geom, ...properties } = row; - const geomObj = typeof geometry === 'string' ? JSON.parse(geometry) : geometry; - return { - type: "Feature", - geometry: geomObj, - properties: properties - }; - }) - }; - res.json(geojson); - } catch (err) { - console.error(err); - res.status(500).json({ error: 'Failed to fetch usage data' }); - } finally { - client.release(); - } -}); - -// 2.5 Get WEA Data (Windturbinen) -app.get('/api/wea', async (req, res) => { - const client = await pool.connect(); - try { - await setSchema(client); - let result; - try { - result = await client.query(` - SELECT - *, - ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry - FROM bw_scheddebrock."WEA" - `); - } catch (dbErr) { - console.log("WEA Tabelle fehlt oder nicht abrufbar."); - result = { rows: [], rowCount: 0 }; - } - - const geojson = { - type: "FeatureCollection", - features: result.rows.map(row => { - const { geometry, geom, ...properties } = row; - const geomObj = typeof geometry === 'string' ? JSON.parse(geometry) : geometry; - return { - type: "Feature", - geometry: geomObj, - properties: properties - }; - }) - }; - res.json(geojson); - } catch (err) { - console.error(err); - res.status(500).json({ error: 'Failed to fetch WEA data' }); - } finally { - client.release(); - } -}); - -// 2.7 Get Infrastructure Data (UW, etc) -app.get('/api/infrastructure', async (req, res) => { - const client = await pool.connect(); - try { - await setSchema(client); - let result; - try { - result = await client.query(` - SELECT - *, - ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry - FROM bw_scheddebrock."Infrastruktur" - `); - } catch (dbErr) { - console.log("Infrastruktur Tabelle fehlt oder nicht abrufbar."); - result = { rows: [], rowCount: 0 }; - } - - const geojson = { - type: "FeatureCollection", - features: result.rows.map(row => { - const { geometry, geom, ...properties } = row; - const geomObj = typeof geometry === 'string' ? JSON.parse(geometry) : (geometry || null); - return { - type: "Feature", - geometry: geomObj, - properties: properties - }; - }) - }; - res.json(geojson); - } catch (err) { - console.error(err); - res.status(500).json({ error: 'Failed to fetch infrastructure data' }); - } finally { - client.release(); - } -}); - -// 3. Get Variants (Kabeltrasse) -app.get('/api/variants', async (req, res) => { - const client = await pool.connect(); - try { - await setSchema(client); - - // Log count - const countRes = await client.query('SELECT count(*) FROM bw_scheddebrock."Kabeltrasse"'); - console.log(`Datenbank-Check: ${countRes.rows[0].count} Kabeltrassen in bw_scheddebrock."Kabeltrasse" gefunden.`); - - const query = ` - SELECT - id_0 as id, name, "Variante", - ST_AsGeoJSON(ST_Transform(ST_SetSRID(geom, 25832), 4326)) as geometry - FROM bw_scheddebrock."Kabeltrasse" - ORDER BY id_0 DESC - `; - const result = await client.query(query); - console.log(`Abfrage erfolgreich: ${result.rowCount} Trassen geladen.`); - - const variants = result.rows.map(row => { - let routes = []; - const geomObj = typeof row.geometry === 'string' ? JSON.parse(row.geometry) : row.geometry; - if (geomObj && geomObj.coordinates) { - if (geomObj.type === 'MultiLineString') { - routes = geomObj.coordinates.map(line => line.map(c => ({ lat: c[1], lng: c[0] }))); - } else if (geomObj.type === 'LineString') { - routes = geomObj.coordinates.map(c => ({ lat: c[1], lng: c[0] })); - } - } - return { - id: row.id, - name: row.name || row.Variante || 'Trasse', - active: false, - visible: true, - stats: { total: 0, drilling: 0, open: 0, muffen: 0 }, - routes: routes - }; - }); - res.json(variants); - } catch (err) { - console.error(err); - res.status(500).json({ error: 'Failed to fetch variants' }); - } finally { - client.release(); - } -}); - -// 4. Save/Update Variant -app.post('/api/variants', async (req, res) => { - console.log("Empfangene Daten (Payload):", JSON.stringify(req.body).substring(0, 200) + "..."); - const { geometry, properties } = req.body; - const client = await pool.connect(); - try { - await setSchema(client); - - console.log("Starte PostgreSQL-Query..."); - - // Clean UPSERT by Database ID. - const routeId = req.body.id; - const routeName = properties.name || 'Neue Trasse'; - const variante = properties.Variante || properties.name || 'A'; - const geoJsonStr = JSON.stringify(geometry); - - // Check if the passed ID is a valid database ID (small int) vs a frontend dummy Date.now() timestamp - // Or try to match it initially just in case it's a known database row. - const existing = await client.query('SELECT id_0 FROM bw_scheddebrock."Kabeltrasse" WHERE id_0 = $1', [Number(routeId) || 0]); - - let result; - if (existing.rowCount > 0) { - // EXACT match found physically in DB, do an UPDATE - const updateQuery = ` - UPDATE bw_scheddebrock."Kabeltrasse" - SET geom = ST_MakeValid(ST_SetSRID(ST_Transform(ST_SetSRID(ST_GeomFromGeoJSON($1), 4326), 25832), 25832)), - name = $2, - "Variante" = $3 - WHERE id_0 = $4 - RETURNING id_0 as id; - `; - result = await client.query(updateQuery, [geoJsonStr, routeName, variante, existing.rows[0].id_0]); - console.log(`PostgreSQL-Ergebnis: Zeile ${existing.rows[0].id_0} aktualisiert (Variante: ${routeName})!`); - } else { - // INSERT new - const insertQuery = ` - INSERT INTO bw_scheddebrock."Kabeltrasse" (geom, name, "Variante") - VALUES (ST_MakeValid(ST_SetSRID(ST_Transform(ST_SetSRID(ST_GeomFromGeoJSON($1), 4326), 25832), 25832)), $2, $3) - RETURNING id_0 as id; - `; - result = await client.query(insertQuery, [geoJsonStr, routeName, variante]); - console.log(`PostgreSQL-Ergebnis: Zeile eingefügt! ID: ${result.rows[0].id}`); - } - - res.json({ success: true, id: result.rows[0].id }); - } catch (err) { - console.error("KRITISCHER SQL-FEHLER:", err.message); - res.status(500).json({ error: 'Failed to save variant: ' + err.message }); - } finally { - client.release(); - } -}); - -// 5. Update Owner Note/Status -app.patch('/api/owners/:id', async (req, res) => { - const { id } = req.params; - const { status, notiz } = req.body; - const client = await pool.connect(); - try { - await setSchema(client); - const query = ` - UPDATE bw_scheddebrock."Eigentuemerdaten" - SET status = $1, notiz = $2 - WHERE id = $3 - RETURNING id; - `; - const result = await client.query(query, [status, notiz, id]); - if (result.rowCount === 0) { - return res.status(404).json({ error: 'Owner not found in database' }); - } - res.json({ success: true, id: result.rows[0].id }); - } catch (err) { - console.error("Owner Update Error:", err); - res.status(500).json({ error: 'Failed to update owner' }); - } finally { - client.release(); - } -}); - -app.listen(port, () => { - console.log(`Server running at http://localhost:${port}`); -}); +// Beispiel-Query: +await client.query('ALTER TABLE wind_projekt_bwscheddebrock."Kabeltrasse" ALTER COLUMN id_0 TYPE BIGINT'); \ No newline at end of file