const express = require('express'); const { Pool } = require('pg'); const { v4: uuidv4 } = require('uuid'); const router = express.Router(); // Database pool const pool = new Pool({ host: process.env.DB_HOST || 'db', port: process.env.DB_PORT || 5432, database: process.env.DB_NAME || 'steuer', user: process.env.DB_USER || 'app', password: process.env.DB_PASSWORD || 'app123', }); // GET /api/customers - Alle Kunden router.get('/', async (req, res) => { try { const { search, limit = 100 } = req.query; let query = ` SELECT k.*, (SELECT COUNT(*) FROM rechnungen WHERE kunde = k.name) as rechnungen_count, (SELECT COALESCE(SUM(betrag), 0) FROM rechnungen WHERE kunde = k.name AND status = 'bezahlt') as total_umsatz FROM kunden k `; const values = []; if (search) { query += ` WHERE k.name ILIKE $1 OR k.email ILIKE $1 OR k.adresse ILIKE $1`; values.push(`%${search}%`); } query += ` ORDER BY k.name ASC LIMIT $${values.length + 1}`; values.push(limit); const result = await pool.query(query, values); res.json({ success: true, customers: result.rows.map(row => ({ ...row, rechnungen_count: parseInt(row.rechnungen_count) || 0, total_umsatz: parseFloat(row.total_umsatz) || 0 })) }); } catch (error) { console.error('Customers List Error:', error); res.status(500).json({ success: false, error: error.message }); } }); // GET /api/customers/:id - Einzelner Kunde router.get('/:id', async (req, res) => { try { const { id } = req.params; // Kunde + Rechnungen const [kundeResult, rechnungenResult] = await Promise.all([ pool.query('SELECT * FROM kunden WHERE id = $1', [id]), pool.query(` SELECT * FROM rechnungen WHERE kunde = (SELECT name FROM kunden WHERE id = $1) ORDER BY datum DESC `, [id]) ]); if (kundeResult.rows.length === 0) { return res.status(404).json({ success: false, error: 'Kunde nicht gefunden' }); } const kunde = kundeResult.rows[0]; const rechnungen = rechnungenResult.rows; // Zusammenfassung const totalUmsatz = rechnungen.reduce((sum, r) => sum + parseFloat(r.betrag || 0), 0); const paidUmsatz = rechnungen .filter(r => r.status === 'bezahlt') .reduce((sum, r) => sum + parseFloat(r.betrag || 0), 0); const openUmsatz = rechnungen .filter(r => r.status === 'offen') .reduce((sum, r) => sum + parseFloat(r.betrag || 0), 0); res.json({ success: true, customer: { ...kunde, rechnungen, summary: { total_rechnungen: rechnungen.length, total_umsatz: totalUmsatz, paid_umsatz: paidUmsatz, open_umsatz: openUmsatz } } }); } catch (error) { console.error('Customer Detail Error:', error); res.status(500).json({ success: false, error: error.message }); } }); // POST /api/customers - Kunde erstellen router.post('/', async (req, res) => { try { const { name, adresse, plz, ort, email, telefon, notizen } = req.body; if (!name) { return res.status(400).json({ success: false, error: 'Name ist erforderlich' }); } const query = ` INSERT INTO kunden (id, name, adresse, plz, ort, email, telefon, notizen, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW(), NOW()) RETURNING * `; const values = [uuidv4(), name, adresse || null, plz || null, ort || null, email || null, telefon || null, notizen || null]; const result = await pool.query(query, values); res.status(201).json({ success: true, customer: result.rows[0] }); } catch (error) { console.error('Customer Create Error:', error); if (error.code === '23505') { return res.status(409).json({ success: false, error: 'Kunde mit diesem Namen existiert bereits' }); } res.status(500).json({ success: false, error: error.message }); } }); // PUT /api/customers/:id - Kunde aktualisieren router.put('/:id', async (req, res) => { try { const { id } = req.params; const { name, adresse, plz, ort, email, telefon, notizen } = req.body; const query = ` UPDATE kunden SET name = COALESCE($1, name), adresse = COALESCE($2, adresse), plz = COALESCE($3, plz), ort = COALESCE($4, ort), email = COALESCE($5, email), telefon = COALESCE($6, telefon), notizen = COALESCE($7, notizen), updated_at = NOW() WHERE id = $8 RETURNING * `; const values = [name, adresse, plz, ort, email, telefon, notizen, id]; const result = await pool.query(query, values); if (result.rows.length === 0) { return res.status(404).json({ success: false, error: 'Kunde nicht gefunden' }); } res.json({ success: true, customer: result.rows[0] }); } catch (error) { console.error('Customer Update Error:', error); res.status(500).json({ success: false, error: error.message }); } }); // DELETE /api/customers/:id - Kunde löschen router.delete('/:id', async (req, res) => { try { const { id } = req.params; // Prüfe ob Kunde Rechnungen hat const checkResult = await pool.query(` SELECT COUNT(*) as count FROM rechnungen WHERE kunde = (SELECT name FROM kunden WHERE id = $1) `, [id]); if (parseInt(checkResult.rows[0].count) > 0) { return res.status(400).json({ success: false, error: 'Kunde kann nicht gelöscht werden - es existieren Rechnungen' }); } const result = await pool.query('DELETE FROM kunden WHERE id = $1 RETURNING *', [id]); if (result.rows.length === 0) { return res.status(404).json({ success: false, error: 'Kunde nicht gefunden' }); } res.json({ success: true, message: 'Kunde erfolgreich gelöscht', deleted: result.rows[0] }); } catch (error) { console.error('Customer Delete Error:', error); res.status(500).json({ success: false, error: error.message }); } }); module.exports = router;