const express = require('express'); const { authenticateToken } = require('../../middleware/auth'); const router = express.Router(); // Debug: Get JTL Kontierung data for a specific JTL Umsatz (by kZahlungsabgleichUmsatz) router.get('/jtl-kontierung/:jtlId', authenticateToken, async (req, res) => { try { const { executeQuery } = require('../../config/database'); const { jtlId } = req.params; const query = ` SELECT uk.data FROM eazybusiness.dbo.tZahlungsabgleichUmsatz z LEFT JOIN eazybusiness.dbo.tUmsatzKontierung uk ON uk.kZahlungsabgleichUmsatz = z.kZahlungsabgleichUmsatz WHERE z.kZahlungsabgleichUmsatz = @jtlId `; const result = await executeQuery(query, { jtlId: parseInt(jtlId, 10) }); // Return undefined when no data found (do not lie with empty array/string) if (!result.recordset || result.recordset.length === 0) { return res.json({ data: undefined }); } // If multiple rows exist, return all; otherwise single object const rows = result.recordset.map(r => ({ data: r.data })); if (rows.length === 1) { return res.json(rows[0]); } return res.json(rows); } catch (error) { console.error('Error fetching JTL Kontierung data:', error); res.status(500).json({ error: 'Failed to fetch JTL Kontierung data' }); } }); // Get accounting items for a specific transaction router.get('/accounting-items/:transactionId', authenticateToken, async (req, res) => { try { const { executeQuery } = require('../../config/database'); const { transactionId } = req.params; // Try both numeric and string format (similar to banking transactions) let query, params; const numericId = parseInt(transactionId, 10); if (!isNaN(numericId) && numericId.toString() === transactionId) { // It's a numeric ID - check transaction_id column query = ` SELECT ai.*, k.name as konto_name, bu.name as bu_name, bu.vst as bu_vst FROM fibdash.AccountingItems ai LEFT JOIN fibdash.Konto k ON ai.konto = k.konto LEFT JOIN fibdash.BU bu ON ai.bu = bu.bu WHERE ai.transaction_id = @transactionId ORDER BY ai.id `; params = { transactionId: numericId }; } else { // It's a string ID - check csv_transaction_id column query = ` SELECT ai.*, k.name as konto_name, bu.name as bu_name, bu.vst as bu_vst FROM fibdash.AccountingItems ai LEFT JOIN fibdash.Konto k ON ai.konto = k.konto LEFT JOIN fibdash.BU bu ON ai.bu = bu.bu WHERE ai.csv_transaction_id = @transactionId ORDER BY ai.id `; params = { transactionId }; } const result = await executeQuery(query, params); res.json(result.recordset); } catch (error) { console.error('Error fetching accounting items:', error); res.status(500).json({ error: 'Failed to fetch accounting items' }); } }); // Create accounting item for a transaction router.post('/accounting-items', authenticateToken, async (req, res) => { try { const { executeQuery } = require('../../config/database'); const { transaction_id, csv_transaction_id, umsatz_brutto, soll_haben_kz, konto, bu, buchungsdatum, rechnungsnummer, buchungstext } = req.body; if ((!transaction_id && !csv_transaction_id) || !umsatz_brutto || !soll_haben_kz || !konto || !buchungsdatum) { return res.status(400).json({ error: 'Transaction ID, amount, debit/credit indicator, account, and booking date are required' }); } let insertQuery, queryParams; if (csv_transaction_id) { // For CSV transactions, use placeholder transaction_id insertQuery = ` INSERT INTO fibdash.AccountingItems (transaction_id, csv_transaction_id, umsatz_brutto, soll_haben_kz, konto, gegenkonto, bu, buchungsdatum, rechnungsnummer, buchungstext) OUTPUT INSERTED.* VALUES (-1, @csv_transaction_id, @umsatz_brutto, @soll_haben_kz, @konto, '', @bu, @buchungsdatum, @rechnungsnummer, @buchungstext) `; queryParams = { csv_transaction_id, umsatz_brutto, soll_haben_kz, konto, bu: bu || null, buchungsdatum, rechnungsnummer: rechnungsnummer || null, buchungstext: buchungstext || null }; } else { // For regular transactions insertQuery = ` INSERT INTO fibdash.AccountingItems (transaction_id, csv_transaction_id, umsatz_brutto, soll_haben_kz, konto, gegenkonto, bu, buchungsdatum, rechnungsnummer, buchungstext) OUTPUT INSERTED.* VALUES (@transaction_id, NULL, @umsatz_brutto, @soll_haben_kz, @konto, '', @bu, @buchungsdatum, @rechnungsnummer, @buchungstext) `; queryParams = { transaction_id, umsatz_brutto, soll_haben_kz, konto, bu: bu || null, buchungsdatum, rechnungsnummer: rechnungsnummer || null, buchungstext: buchungstext || null }; } const result = await executeQuery(insertQuery, queryParams); res.status(201).json(result.recordset[0]); } catch (error) { console.error('Error creating accounting item:', error); res.status(500).json({ error: 'Failed to create accounting item' }); } }); // Update accounting item router.put('/accounting-items/:id', authenticateToken, async (req, res) => { try { const { executeQuery } = require('../../config/database'); const { id } = req.params; const { umsatz_brutto, soll_haben_kz, konto, bu, rechnungsnummer, buchungstext } = req.body; if (!umsatz_brutto || !soll_haben_kz || !konto) { return res.status(400).json({ error: 'Amount, debit/credit indicator, and account are required' }); } const updateQuery = ` UPDATE fibdash.AccountingItems SET umsatz_brutto = @umsatz_brutto, soll_haben_kz = @soll_haben_kz, konto = @konto, bu = @bu, rechnungsnummer = @rechnungsnummer, buchungstext = @buchungstext OUTPUT INSERTED.* WHERE id = @id `; const result = await executeQuery(updateQuery, { umsatz_brutto, soll_haben_kz, konto, bu: bu || null, rechnungsnummer: rechnungsnummer || null, buchungstext: buchungstext || null, id: parseInt(id, 10) }); if (result.recordset.length === 0) { return res.status(404).json({ error: 'Accounting item not found' }); } res.json(result.recordset[0]); } catch (error) { console.error('Error updating accounting item:', error); res.status(500).json({ error: 'Failed to update accounting item' }); } }); // Delete accounting item router.delete('/accounting-items/:id', authenticateToken, async (req, res) => { try { const { executeQuery } = require('../../config/database'); const { id } = req.params; const deleteQuery = `DELETE FROM fibdash.AccountingItems WHERE id = @id`; await executeQuery(deleteQuery, { id: parseInt(id, 10) }); res.json({ message: 'Accounting item deleted successfully' }); } catch (error) { console.error('Error deleting accounting item:', error); res.status(500).json({ error: 'Failed to delete accounting item' }); } }); // Get all Konto options router.get('/kontos', authenticateToken, async (req, res) => { try { const { executeQuery } = require('../../config/database'); const query = `SELECT * FROM fibdash.Konto ORDER BY konto`; const result = await executeQuery(query); res.json(result.recordset); } catch (error) { console.error('Error fetching kontos:', error); res.status(500).json({ error: 'Failed to fetch kontos' }); } }); // Create new Konto router.post('/kontos', authenticateToken, async (req, res) => { try { const { executeQuery } = require('../../config/database'); const { konto, name } = req.body; if (!konto || !name) { return res.status(400).json({ error: 'Konto and name are required' }); } const insertQuery = ` INSERT INTO fibdash.Konto (konto, name) OUTPUT INSERTED.* VALUES (@konto, @name) `; const result = await executeQuery(insertQuery, { konto, name }); res.status(201).json(result.recordset[0]); } catch (error) { console.error('Error creating konto:', error); res.status(500).json({ error: 'Failed to create konto' }); } }); // Get all BU options router.get('/bus', authenticateToken, async (req, res) => { try { const { executeQuery } = require('../../config/database'); const query = `SELECT * FROM fibdash.BU ORDER BY bu`; const result = await executeQuery(query); res.json(result.recordset); } catch (error) { console.error('Error fetching BUs:', error); res.status(500).json({ error: 'Failed to fetch BUs' }); } }); module.exports = router;