274 lines
9.5 KiB
JavaScript
274 lines
9.5 KiB
JavaScript
const express = require('express');
|
|
const { authenticateToken } = require('../middleware/auth');
|
|
const { checkAuthorizedEmail } = require('../middleware/emailAuth');
|
|
const { executeQuery, sql } = require('../config/database');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const router = express.Router();
|
|
|
|
// Removed admin access check - all authenticated users can access these routes
|
|
|
|
// Get system info
|
|
router.get('/system-info', authenticateToken, (req, res) => {
|
|
res.json({
|
|
currentUser: req.user.email,
|
|
environment: process.env.NODE_ENV || 'development'
|
|
});
|
|
});
|
|
|
|
// ==================== KREDITOR ROUTES ====================
|
|
|
|
// Get all kreditoren
|
|
router.get('/kreditoren', authenticateToken, async (req, res) => {
|
|
try {
|
|
const result = await executeQuery('SELECT id, iban, name, kreditorId, is_banking FROM fibdash.Kreditor ORDER BY name, iban');
|
|
res.json({ kreditoren: result.recordset });
|
|
} catch (error) {
|
|
console.error('Error fetching kreditoren:', error);
|
|
res.status(500).json({ error: 'Fehler beim Laden der Kreditoren' });
|
|
}
|
|
});
|
|
|
|
// Create new kreditor
|
|
router.post('/kreditoren', authenticateToken, async (req, res) => {
|
|
const { iban, name, kreditorId, is_banking } = req.body;
|
|
|
|
// IBAN is optional for banking accounts or manual kreditor assignments
|
|
const isBanking = is_banking || false;
|
|
|
|
if (!name || !kreditorId) {
|
|
return res.status(400).json({ error: 'Name und Kreditor ID sind erforderlich' });
|
|
}
|
|
|
|
// IBAN validation - required for non-banking accounts
|
|
if (!isBanking && (!iban || iban.trim() === '')) {
|
|
return res.status(400).json({ error: 'IBAN ist erforderlich (außer für Banking-Konten)' });
|
|
}
|
|
|
|
try {
|
|
await executeQuery(
|
|
'INSERT INTO fibdash.Kreditor (iban, name, kreditorId, is_banking) VALUES (@iban, @name, @kreditorId, @is_banking)',
|
|
{ iban: iban || null, name, kreditorId, is_banking: isBanking }
|
|
);
|
|
res.json({ message: 'Kreditor erfolgreich erstellt' });
|
|
} catch (error) {
|
|
console.error('Error creating kreditor:', error);
|
|
if (error.number === 2627) { // Unique constraint violation
|
|
res.status(400).json({ error: 'IBAN oder Kreditor ID bereits vorhanden' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Erstellen des Kreditors' });
|
|
}
|
|
}
|
|
});
|
|
|
|
// Update kreditor
|
|
router.put('/kreditoren/:id', authenticateToken, async (req, res) => {
|
|
const { id } = req.params;
|
|
const { iban, name, kreditorId, is_banking } = req.body;
|
|
|
|
// IBAN is optional for banking accounts or manual kreditor assignments
|
|
const isBanking = is_banking || false;
|
|
|
|
if (!name || !kreditorId) {
|
|
return res.status(400).json({ error: 'Name und Kreditor ID sind erforderlich' });
|
|
}
|
|
|
|
// IBAN validation - required for non-banking accounts
|
|
if (!isBanking && (!iban || iban.trim() === '')) {
|
|
return res.status(400).json({ error: 'IBAN ist erforderlich (außer für Banking-Konten)' });
|
|
}
|
|
|
|
try {
|
|
await executeQuery(
|
|
'UPDATE fibdash.Kreditor SET iban = @iban, name = @name, kreditorId = @kreditorId, is_banking = @is_banking WHERE id = @id',
|
|
{ iban: iban || null, name, kreditorId, is_banking: isBanking, id }
|
|
);
|
|
res.json({ message: 'Kreditor erfolgreich aktualisiert' });
|
|
} catch (error) {
|
|
console.error('Error updating kreditor:', error);
|
|
if (error.number === 2627) { // Unique constraint violation
|
|
res.status(400).json({ error: 'IBAN oder Kreditor ID bereits vorhanden' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Aktualisieren des Kreditors' });
|
|
}
|
|
}
|
|
});
|
|
|
|
// Delete kreditor
|
|
router.delete('/kreditoren/:id', authenticateToken, async (req, res) => {
|
|
const { id } = req.params;
|
|
|
|
try {
|
|
await executeQuery('DELETE FROM fibdash.Kreditor WHERE id = @id', { id });
|
|
res.json({ message: 'Kreditor erfolgreich gelöscht' });
|
|
} catch (error) {
|
|
console.error('Error deleting kreditor:', error);
|
|
if (error.number === 547) { // Foreign key constraint violation
|
|
res.status(400).json({ error: 'Kreditor kann nicht gelöscht werden, da er in Buchungen verwendet wird' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Löschen des Kreditors' });
|
|
}
|
|
}
|
|
});
|
|
|
|
// ==================== KONTO ROUTES ====================
|
|
|
|
// Get all konten
|
|
router.get('/konten', authenticateToken, async (req, res) => {
|
|
try {
|
|
const result = await executeQuery('SELECT * FROM fibdash.Konto ORDER BY konto');
|
|
res.json({ konten: result.recordset });
|
|
} catch (error) {
|
|
console.error('Error fetching konten:', error);
|
|
res.status(500).json({ error: 'Fehler beim Laden der Konten' });
|
|
}
|
|
});
|
|
|
|
// Create new konto
|
|
router.post('/konten', authenticateToken, async (req, res) => {
|
|
const { konto, name } = req.body;
|
|
|
|
if (!konto || !name) {
|
|
return res.status(400).json({ error: 'Konto und Name sind erforderlich' });
|
|
}
|
|
|
|
try {
|
|
await executeQuery(
|
|
'INSERT INTO fibdash.Konto (konto, name) VALUES (@konto, @name)',
|
|
{ konto, name }
|
|
);
|
|
res.json({ message: 'Konto erfolgreich erstellt' });
|
|
} catch (error) {
|
|
console.error('Error creating konto:', error);
|
|
if (error.number === 2627) { // Unique constraint violation
|
|
res.status(400).json({ error: 'Konto bereits vorhanden' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Erstellen des Kontos' });
|
|
}
|
|
}
|
|
});
|
|
|
|
// Update konto
|
|
router.put('/konten/:id', authenticateToken, async (req, res) => {
|
|
const { id } = req.params;
|
|
const { konto, name } = req.body;
|
|
|
|
if (!konto || !name) {
|
|
return res.status(400).json({ error: 'Konto und Name sind erforderlich' });
|
|
}
|
|
|
|
try {
|
|
await executeQuery(
|
|
'UPDATE fibdash.Konto SET konto = @konto, name = @name WHERE id = @id',
|
|
{ konto, name, id }
|
|
);
|
|
res.json({ message: 'Konto erfolgreich aktualisiert' });
|
|
} catch (error) {
|
|
console.error('Error updating konto:', error);
|
|
if (error.number === 2627) { // Unique constraint violation
|
|
res.status(400).json({ error: 'Konto bereits vorhanden' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Aktualisieren des Kontos' });
|
|
}
|
|
}
|
|
});
|
|
|
|
// Delete konto
|
|
router.delete('/konten/:id', authenticateToken, async (req, res) => {
|
|
const { id } = req.params;
|
|
|
|
try {
|
|
await executeQuery('DELETE FROM fibdash.Konto WHERE id = @id', { id });
|
|
res.json({ message: 'Konto erfolgreich gelöscht' });
|
|
} catch (error) {
|
|
console.error('Error deleting konto:', error);
|
|
if (error.number === 547) { // Foreign key constraint violation
|
|
res.status(400).json({ error: 'Konto kann nicht gelöscht werden, da es in Buchungen verwendet wird' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Löschen des Kontos' });
|
|
}
|
|
}
|
|
});
|
|
|
|
// ==================== BU (BUCHUNGSSCHLÜSSEL) ROUTES ====================
|
|
|
|
// Get all buchungsschluessel
|
|
router.get('/buchungsschluessel', authenticateToken, async (req, res) => {
|
|
try {
|
|
const result = await executeQuery('SELECT * FROM fibdash.BU ORDER BY bu');
|
|
res.json({ buchungsschluessel: result.recordset });
|
|
} catch (error) {
|
|
console.error('Error fetching buchungsschluessel:', error);
|
|
res.status(500).json({ error: 'Fehler beim Laden der Buchungsschlüssel' });
|
|
}
|
|
});
|
|
|
|
// Create new buchungsschluessel
|
|
router.post('/buchungsschluessel', authenticateToken, async (req, res) => {
|
|
const { bu, name, vst } = req.body;
|
|
|
|
if (!bu || !name) {
|
|
return res.status(400).json({ error: 'BU und Name sind erforderlich' });
|
|
}
|
|
|
|
try {
|
|
await executeQuery(
|
|
'INSERT INTO fibdash.BU (bu, name, vst) VALUES (@bu, @name, @vst)',
|
|
{ bu, name, vst: vst !== undefined && vst !== '' ? vst : null }
|
|
);
|
|
res.json({ message: 'Buchungsschlüssel erfolgreich erstellt' });
|
|
} catch (error) {
|
|
console.error('Error creating BU:', error);
|
|
if (error.number === 2627) { // Unique constraint violation
|
|
res.status(400).json({ error: 'Buchungsschlüssel bereits vorhanden' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Erstellen des Buchungsschlüssels' });
|
|
}
|
|
}
|
|
});
|
|
|
|
// Update buchungsschluessel
|
|
router.put('/buchungsschluessel/:id', authenticateToken, async (req, res) => {
|
|
const { id } = req.params;
|
|
const { bu, name, vst } = req.body;
|
|
|
|
if (!bu || !name) {
|
|
return res.status(400).json({ error: 'BU und Name sind erforderlich' });
|
|
}
|
|
|
|
try {
|
|
await executeQuery(
|
|
'UPDATE fibdash.BU SET bu = @bu, name = @name, vst = @vst WHERE id = @id',
|
|
{ bu, name, vst: vst !== undefined && vst !== '' ? vst : null, id }
|
|
);
|
|
res.json({ message: 'Buchungsschlüssel erfolgreich aktualisiert' });
|
|
} catch (error) {
|
|
console.error('Error updating BU:', error);
|
|
if (error.number === 2627) { // Unique constraint violation
|
|
res.status(400).json({ error: 'Buchungsschlüssel bereits vorhanden' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Aktualisieren des Buchungsschlüssels' });
|
|
}
|
|
}
|
|
});
|
|
|
|
// Delete buchungsschluessel
|
|
router.delete('/buchungsschluessel/:id', authenticateToken, async (req, res) => {
|
|
const { id } = req.params;
|
|
|
|
try {
|
|
await executeQuery('DELETE FROM fibdash.BU WHERE id = @id', { id });
|
|
res.json({ message: 'Buchungsschlüssel erfolgreich gelöscht' });
|
|
} catch (error) {
|
|
console.error('Error deleting BU:', error);
|
|
if (error.number === 547) { // Foreign key constraint violation
|
|
res.status(400).json({ error: 'Buchungsschlüssel kann nicht gelöscht werden, da er in Buchungen verwendet wird' });
|
|
} else {
|
|
res.status(500).json({ error: 'Fehler beim Löschen des Buchungsschlüssels' });
|
|
}
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|