@fin.cx/skr
Version:
SKR03 and SKR04 German accounting standards for double-entry bookkeeping
205 lines • 16.8 kB
JavaScript
import * as plugins from './plugins.js';
import * as path from 'path';
export class BalancesExporter {
constructor(exportPath, fiscalYear) {
this.balances = [];
this.exportPath = exportPath;
this.fiscalYear = fiscalYear;
}
/**
* Adds a balance entry to the export
*/
addBalance(accountCode, accountName, balance, period) {
const exportRow = {
account_code: accountCode,
account_name: accountName,
fiscal_year: this.fiscalYear,
period: period,
opening_balance: (balance.openingBalance || 0).toFixed(2),
closing_balance: balance.balance.toFixed(2),
debit_sum: balance.debitTotal.toFixed(2),
credit_sum: balance.creditTotal.toFixed(2),
balance: balance.balance.toFixed(2),
transaction_count: balance.transactionCount || 0
};
this.balances.push(exportRow);
}
/**
* Exports balances to CSV format
*/
async exportToCSV() {
const csvPath = path.join(this.exportPath, 'data', 'accounting', 'balances.csv');
await plugins.smartfile.fs.ensureDir(path.dirname(csvPath));
// Create CSV header
const headers = [
'account_code',
'account_name',
'fiscal_year',
'period',
'opening_balance',
'closing_balance',
'debit_sum',
'credit_sum',
'balance',
'transaction_count'
];
let csvContent = headers.join(',') + '\n';
// Sort balances by account code
this.balances.sort((a, b) => a.account_code.localeCompare(b.account_code));
// Add balance rows
for (const balance of this.balances) {
const row = [
this.escapeCSV(balance.account_code),
this.escapeCSV(balance.account_name),
balance.fiscal_year.toString(),
this.escapeCSV(balance.period || ''),
balance.opening_balance,
balance.closing_balance,
balance.debit_sum,
balance.credit_sum,
balance.balance,
balance.transaction_count.toString()
];
csvContent += row.join(',') + '\n';
}
await plugins.smartfile.memory.toFs(csvContent, csvPath);
}
/**
* Exports trial balance (Summen- und Saldenliste)
*/
async exportTrialBalance() {
const csvPath = path.join(this.exportPath, 'data', 'accounting', 'trial_balance.csv');
await plugins.smartfile.fs.ensureDir(path.dirname(csvPath));
// Create CSV header for trial balance
const headers = [
'Konto',
'Bezeichnung',
'Anfangssaldo',
'Soll',
'Haben',
'Saldo',
'Endsaldo'
];
let csvContent = headers.join(',') + '\n';
// Add rows with German formatting
for (const balance of this.balances) {
const row = [
this.escapeCSV(balance.account_code),
this.escapeCSV(balance.account_name),
this.formatGermanNumber(parseFloat(balance.opening_balance)),
this.formatGermanNumber(parseFloat(balance.debit_sum)),
this.formatGermanNumber(parseFloat(balance.credit_sum)),
this.formatGermanNumber(parseFloat(balance.debit_sum) - parseFloat(balance.credit_sum)),
this.formatGermanNumber(parseFloat(balance.closing_balance))
];
csvContent += row.join(',') + '\n';
}
// Add totals row
const totalDebit = this.balances.reduce((sum, b) => sum + parseFloat(b.debit_sum), 0);
const totalCredit = this.balances.reduce((sum, b) => sum + parseFloat(b.credit_sum), 0);
csvContent += '\n';
csvContent += [
'SUMME',
'',
'',
this.formatGermanNumber(totalDebit),
this.formatGermanNumber(totalCredit),
this.formatGermanNumber(totalDebit - totalCredit),
''
].join(',') + '\n';
await plugins.smartfile.memory.toFs(csvContent, csvPath);
}
/**
* Exports balances to JSON format
*/
async exportToJSON() {
const jsonPath = path.join(this.exportPath, 'data', 'accounting', 'balances.json');
await plugins.smartfile.fs.ensureDir(path.dirname(jsonPath));
const jsonData = {
schema_version: '1.0',
export_date: new Date().toISOString(),
fiscal_year: this.fiscalYear,
balances: this.balances,
totals: {
total_debit: this.balances.reduce((sum, b) => sum + parseFloat(b.debit_sum), 0).toFixed(2),
total_credit: this.balances.reduce((sum, b) => sum + parseFloat(b.credit_sum), 0).toFixed(2),
account_count: this.balances.length
}
};
await plugins.smartfile.memory.toFs(JSON.stringify(jsonData, null, 2), jsonPath);
}
/**
* Generates balance summary for specific account classes
*/
async exportClassSummary() {
const csvPath = path.join(this.exportPath, 'data', 'accounting', 'class_summary.csv');
await plugins.smartfile.fs.ensureDir(path.dirname(csvPath));
// Group balances by account class (first digit of account code)
const classSummary = {};
for (const balance of this.balances) {
const accountClass = balance.account_code.charAt(0);
if (!classSummary[accountClass]) {
classSummary[accountClass] = { debit: 0, credit: 0, balance: 0 };
}
classSummary[accountClass].debit += parseFloat(balance.debit_sum);
classSummary[accountClass].credit += parseFloat(balance.credit_sum);
classSummary[accountClass].balance += parseFloat(balance.balance);
}
// Create CSV
let csvContent = 'Kontenklasse,Bezeichnung,Soll,Haben,Saldo\n';
const classNames = {
'0': 'Anlagevermögen',
'1': 'Umlaufvermögen',
'2': 'Eigenkapital',
'3': 'Fremdkapital',
'4': 'Betriebliche Erträge',
'5': 'Materialaufwand',
'6': 'Betriebsaufwand',
'7': 'Weitere Aufwendungen',
'8': 'Erträge',
'9': 'Abschlusskonten'
};
for (const [classNum, summary] of Object.entries(classSummary)) {
const row = [
classNum,
this.escapeCSV(classNames[classNum] || `Klasse ${classNum}`),
this.formatGermanNumber(summary.debit),
this.formatGermanNumber(summary.credit),
this.formatGermanNumber(summary.balance)
];
csvContent += row.join(',') + '\n';
}
await plugins.smartfile.memory.toFs(csvContent, csvPath);
}
/**
* Escapes CSV values
*/
escapeCSV(value) {
if (value.includes(',') || value.includes('"') || value.includes('\n')) {
return `"${value.replace(/"/g, '""')}"`;
}
return value;
}
/**
* Formats number in German format (1.234,56)
*/
formatGermanNumber(value) {
return value.toLocaleString('de-DE', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
}
/**
* Gets the number of balance entries
*/
getBalanceCount() {
return this.balances.length;
}
/**
* Clears the balances list
*/
clear() {
this.balances = [];
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmV4cG9ydC5iYWxhbmNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3Nrci5leHBvcnQuYmFsYW5jZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFzQjdCLE1BQU0sT0FBTyxnQkFBZ0I7SUFLM0IsWUFBWSxVQUFrQixFQUFFLFVBQWtCO1FBSDFDLGFBQVEsR0FBd0IsRUFBRSxDQUFDO1FBSXpDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO0lBQy9CLENBQUM7SUFFRDs7T0FFRztJQUNJLFVBQVUsQ0FDZixXQUFtQixFQUNuQixXQUFtQixFQUNuQixPQUE4QixFQUM5QixNQUFlO1FBRWYsTUFBTSxTQUFTLEdBQXNCO1lBQ25DLFlBQVksRUFBRSxXQUFXO1lBQ3pCLFlBQVksRUFBRSxXQUFXO1lBQ3pCLFdBQVcsRUFBRSxJQUFJLENBQUMsVUFBVTtZQUM1QixNQUFNLEVBQUUsTUFBTTtZQUNkLGVBQWUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxjQUFjLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUN6RCxlQUFlLEVBQUUsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQzNDLFNBQVMsRUFBRSxPQUFPLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDeEMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUMxQyxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ25DLGlCQUFpQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDO1NBQ2pELENBQUM7UUFF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