bwscheddebrock_trassenplaner/server.js

279 lines
7.4 KiB
JavaScript

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
async function setSchema(client) {
const schema = process.env.DB_SCHEMA || 'wind_projekt_bwscheddebrock';
await client.query(`SET search_path TO "${schema}", public;`);
}
// --- API Routes ---
app.get('/api/health', (req, res) => {
res.json({ status: 'OK', schema: process.env.DB_SCHEMA, time: new Date().toISOString() });
});
// 1. Get Owner Data
app.get('/api/owners', async (req, res) => {
const client = await pool.connect();
try {
await setSchema(client);
const query = `
SELECT
id,
nachname AS "Nachname",
vorname AS "Vorname",
ort AS "Ort",
"Flur" AS "Flur",
"FlSt" AS "Flurstueck",
"Gema" AS "Gemarkung",
"PLZ" AS "PLZ",
"Land" AS "Land",
"AFlaeche" AS "AFlaeche",
status,
notiz,
ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry
FROM eigentuemerdaten
`;
const result = await client.query(query);
const geojson = {
type: "FeatureCollection",
features: result.rows.map(row => {
const { geometry, ...properties } = row;
return {
type: "Feature",
id: row.id,
geometry: JSON.parse(geometry),
properties: properties
};
})
};
res.json(geojson);
} catch (err) {
console.error("Owner Fetch 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);
const query = `
SELECT
id,
nutzart AS "nutzart",
bez AS "bez",
ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry
FROM nutzung
`;
const result = await client.query(query);
const geojson = {
type: "FeatureCollection",
features: result.rows.map(row => {
const { geometry, ...properties } = row;
return {
type: "Feature",
geometry: JSON.parse(geometry),
properties: properties
};
})
};
res.json(geojson);
} catch (err) {
console.error("Usage Error:", err);
res.json({ type: "FeatureCollection", features: [] });
} finally {
client.release();
}
});
// 2.5 Get WEA Data
app.get('/api/wea', async (req, res) => {
const client = await pool.connect();
try {
await setSchema(client);
const query = `
SELECT
id,
"WEA" AS "Name",
"GH" AS "GH",
ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry
FROM wea
`;
const result = await client.query(query);
const geojson = {
type: "FeatureCollection",
features: result.rows.map(row => {
const { geometry, ...properties } = row;
return {
type: "Feature",
geometry: JSON.parse(geometry),
properties: properties
};
})
};
res.json(geojson);
} catch (err) {
console.error("WEA Error:", err);
res.json({ type: "FeatureCollection", features: [] });
} finally {
client.release();
}
});
// 2.7 Get Infrastructure Data
app.get('/api/infrastructure', async (req, res) => {
const client = await pool.connect();
try {
await setSchema(client);
const query = `
SELECT
id,
ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry
FROM infrastruktur
`;
const result = await client.query(query);
const geojson = {
type: "FeatureCollection",
features: result.rows.map(row => {
const { geometry, ...properties } = row;
return {
type: "Feature",
geometry: JSON.parse(geometry),
properties: properties
};
})
};
res.json(geojson);
} catch (err) {
res.json({ type: "FeatureCollection", features: [] });
} finally {
client.release();
}
});
// 3. Get Variants (Kabeltrasse)
app.get('/api/variants', async (req, res) => {
const client = await pool.connect();
try {
await setSchema(client);
const query = `
SELECT
COALESCE(id, fid) AS id, name, "Variante",
ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry
FROM kabeltrasse
ORDER BY id DESC
`;
const result = await client.query(query);
const featureCollection = {
type: "FeatureCollection",
features: result.rows.map(row => {
return {
type: "Feature",
id: row.id,
geometry: JSON.parse(row.geometry || 'null'),
properties: {
id: row.id,
name: row.name || (row.Variante ? `Variante ${row.Variante}` : 'Neue Trasse'),
Variante: row.Variante
}
};
})
};
res.json(featureCollection);
} catch (err) {
res.json({ type: "FeatureCollection", features: [] });
} finally {
client.release();
}
});
// 4. Save/Update Variant
app.post('/api/variants', async (req, res) => {
const { geometry, properties } = req.body;
const client = await pool.connect();
try {
await setSchema(client);
const routeName = properties.name || 'Neue Trasse';
const varianteValue = properties.Variante || (properties.name ? properties.name.replace('Variante ', '') : 'A');
const geoJsonStr = JSON.stringify(geometry);
// Delete existing variant if it exists (Manual UPSERT to bypass missing index permissions)
await client.query('DELETE FROM kabeltrasse WHERE "Variante" = $1 OR name = $2', [varianteValue, routeName]);
const insertQuery = `
INSERT INTO kabeltrasse (geom, name, "Variante")
VALUES (
ST_MakeValid(ST_Transform(ST_GeomFromGeoJSON($1), 25832)),
$2,
$3
)
RETURNING id
`;
const insertRes = await client.query(insertQuery, [geoJsonStr, routeName, varianteValue]);
res.json({ success: true, id: insertRes.rows[0].id });
} catch (err) {
console.error("SQL-FEHLER (SAVE):", err.message);
res.status(500).json({ error: 'Failed to save variant' });
} 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 eigentuemerdaten
SET status = $1, notiz = $2
WHERE id = $3
RETURNING id;
`;
const result = await client.query(query, [status, notiz, id]);
res.json({ success: true, id: result.rows[0]?.id });
} catch (err) {
console.error("Update Owner Error:", err);
res.status(500).json({ error: 'Failed to update owner' });
} finally {
client.release();
}
});
app.listen(3000, () => {
console.log(`Server running at http://localhost:3000`);
});