bwscheddebrock_trassenplaner/server.js

288 lines
7.6 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;`);
}
// Database Initial Setup / Migration Logic Removed
// (Now treating existing tables as the read-only 'Source of Truth')
// --- 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);
// Using exact quoted names to preserve case-sensitivity
const query = `
SELECT
"id",
"Nachname",
"Vorname",
"Ort",
"Flur",
"Flurstueck",
"Gemarkung",
"status" as "status",
"notiz" as "notiz",
"Str_HNr",
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",
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 Fetch Error:", err);
res.status(500).json({ error: 'Failed to fetch usage data' });
} 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",
"Name",
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) {
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
"id", "name", "Variante",
ST_AsGeoJSON(ST_Transform(ST_SetSRID("geom", 25832), 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) {
console.error("Variants Fetch 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) => {
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);
// Using exact quoted column names for the UPSERT
const upsertQuery = `
INSERT INTO "kabeltrasse" ("geom", "name", "Variante")
VALUES (
ST_MakeValid(ST_Transform(ST_SetSRID(ST_GeomFromGeoJSON($1), 4326), 25832)),
$2,
$3
)
ON CONFLICT ("Variante")
DO UPDATE SET
"geom" = EXCLUDED."geom",
"name" = EXCLUDED."name"
RETURNING "id"
`;
const upsertRes = await client.query(upsertQuery, [geoJsonStr, routeName, varianteValue]);
res.json({ success: true, id: upsertRes.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]);
if (result.rowCount === 0) return res.status(404).json({ error: 'Owner not found' });
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(port, () => {
console.log(`Server running at http://localhost:${port}`);
});