Add Accounting Items Management and SQL Integration
- Introduced AccountingItemsManager component for managing accounting entries within transactions. - Implemented API routes for creating, retrieving, updating, and deleting accounting items. - Added SQL queries to handle accounting items linked to transactions, supporting both numeric and string transaction IDs. - Enhanced CSV import functionality to include new accounting item handling. - Created mssql.md documentation for SQL command usage related to accounting items.
This commit is contained in:
240
src/routes/data/accountingItems.js
Normal file
240
src/routes/data/accountingItems.js
Normal file
@@ -0,0 +1,240 @@
|
||||
const express = require('express');
|
||||
const { authenticateToken } = require('../../middleware/auth');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// 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;
|
||||
Reference in New Issue
Block a user