Initial commit - Stand 26.04.2026

This commit is contained in:
OpenClaw
2026-04-26 07:51:39 +02:00
commit b29c467187
186 changed files with 39281 additions and 0 deletions
+151
View File
@@ -0,0 +1,151 @@
// API Routes für Private Finanzen (Monatliche Ausgaben, etc.)
const { Pool } = require('pg');
const pool = new Pool({
host: process.env.DB_HOST || 'buchhaltung-db',
port: process.env.DB_PORT || 5432,
database: process.env.DB_NAME || 'buchhaltung',
user: process.env.DB_USER || 'postgres',
password: process.env.DB_PASSWORD || 'postgres',
});
module.exports = (app) => {
// ========== PRIVAT AUSGABEN ==========
// Tabelle erstellen falls nicht existiert
app.post('/api/privat/init', async (req, res) => {
try {
await pool.query(`
CREATE TABLE IF NOT EXISTS privat_ausgaben (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
kategorie VARCHAR(100) NOT NULL,
bezeichnung VARCHAR(255),
betrag DECIMAL(10,2) NOT NULL,
jahr INTEGER NOT NULL,
monat INTEGER NOT NULL, -- 0-11 für Jan-Dez
typ VARCHAR(20) DEFAULT 'einmalig', -- 'einmalig' oder 'wiederkehrend'
wiederkehrend_bis INTEGER, -- Monat bis zu dem es wiederkehrt (optional)
wiederkehrend_bis_jahr INTEGER,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
)
`);
res.json({ success: true, message: 'Tabelle privat_ausgaben erstellt' });
} catch (error) {
console.error('Init Error:', error);
res.status(500).json({ error: error.message });
}
});
// Alle Ausgaben für Jahr/Monat laden
app.get('/api/privat/ausgaben', async (req, res) => {
try {
const { jahr, monat } = req.query;
let query = 'SELECT * FROM privat_ausgaben WHERE 1=1';
const params = [];
let paramCount = 0;
if (jahr) {
paramCount++;
query += ` AND (jahr = $${paramCount} OR (typ = 'wiederkehrend' AND jahr <= $${paramCount}))`;
params.push(parseInt(jahr));
}
if (monat !== undefined) {
paramCount++;
query += ` AND (monat = $${paramCount} OR typ = 'wiederkehrend')`;
params.push(parseInt(monat));
}
query += ' ORDER BY created_at DESC';
const result = await pool.query(query, params);
res.json(result.rows);
} catch (error) {
// Tabelle existiert nicht - leeres Array zurückgeben
if (error.message.includes('relation "privat_ausgaben" does not exist')) {
return res.json([]);
}
console.error('Load Error:', error);
res.status(500).json({ error: error.message });
}
});
// Ausgabe erstellen
app.post('/api/privat/ausgaben', async (req, res) => {
try {
const { kategorie, bezeichnung, betrag, jahr, monat, typ, wiederkehrend_bis, wiederkehrend_bis_jahr } = req.body;
// Tabelle erstellen falls nicht existiert
await pool.query(`
CREATE TABLE IF NOT EXISTS privat_ausgaben (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
kategorie VARCHAR(100) NOT NULL,
bezeichnung VARCHAR(255),
betrag DECIMAL(10,2) NOT NULL,
jahr INTEGER NOT NULL,
monat INTEGER NOT NULL,
typ VARCHAR(20) DEFAULT 'einmalig',
wiederkehrend_bis INTEGER,
wiederkehrend_bis_jahr INTEGER,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
)
`);
const result = await pool.query(
`INSERT INTO privat_ausgaben (kategorie, bezeichnung, betrag, jahr, monat, typ, wiederkehrend_bis, wiederkehrend_bis_jahr)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *`,
[kategorie, bezeichnung, betrag, jahr, monat, typ || 'einmalig', wiederkehrend_bis, wiederkehrend_bis_jahr]
);
res.json(result.rows[0]);
} catch (error) {
console.error('Create Error:', error);
res.status(500).json({ error: error.message });
}
});
// Ausgabe aktualisieren
app.put('/api/privat/ausgaben/:id', async (req, res) => {
try {
const { kategorie, bezeichnung, betrag, jahr, monat, typ, wiederkehrend_bis, wiederkehrend_bis_jahr } = req.body;
const result = await pool.query(
`UPDATE privat_ausgaben
SET kategorie = $1, bezeichnung = $2, betrag = $3, jahr = $4, monat = $5,
typ = $6, wiederkehrend_bis = $7, wiederkehrend_bis_jahr = $8, updated_at = NOW()
WHERE id = $9 RETURNING *`,
[kategorie, bezeichnung, betrag, jahr, monat, typ, wiederkehrend_bis, wiederkehrend_bis_jahr, req.params.id]
);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'Ausgabe nicht gefunden' });
}
res.json(result.rows[0]);
} catch (error) {
console.error('Update Error:', error);
res.status(500).json({ error: error.message });
}
});
// Ausgabe löschen
app.delete('/api/privat/ausgaben/:id', async (req, res) => {
try {
const result = await pool.query('DELETE FROM privat_ausgaben WHERE id = $1 RETURNING *', [req.params.id]);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'Ausgabe nicht gefunden' });
}
res.json({ success: true, deleted: result.rows[0] });
} catch (error) {
console.error('Delete Error:', error);
res.status(500).json({ error: error.message });
}
});
};