@fin.cx/skr
Version:
SKR03 and SKR04 German accounting standards for double-entry bookkeeping
164 lines • 12.8 kB
JavaScript
import * as plugins from './plugins.js';
import * as path from 'path';
import { createWriteStream } from 'fs';
export class LedgerExporter {
constructor(exportPath) {
this.stream = null;
this.entryCount = 0;
this.exportPath = exportPath;
}
/**
* Initializes the NDJSON export stream
*/
async initialize() {
const ledgerPath = path.join(this.exportPath, 'data', 'accounting', 'ledger.ndjson');
await plugins.smartfile.fs.ensureDir(path.dirname(ledgerPath));
this.stream = createWriteStream(ledgerPath, {
encoding: 'utf8',
flags: 'w'
});
}
/**
* Exports a transaction as a ledger entry
*/
async exportTransaction(transaction) {
if (!this.stream) {
throw new Error('Ledger exporter not initialized');
}
const entry = {
schema_version: '1.0',
entry_id: transaction._id || plugins.smartunique.shortId(),
booking_date: this.formatDate(transaction.date),
posting_date: this.formatDate(transaction.postingDate || transaction.date),
currency: transaction.currency || 'EUR',
journal: 'GL',
description: transaction.description,
reference: transaction.reference,
lines: [],
created_at: transaction.createdAt ? new Date(transaction.createdAt).toISOString() : new Date().toISOString(),
modified_at: transaction.modifiedAt ? new Date(transaction.modifiedAt).toISOString() : undefined,
reversal_of: transaction.reversalOf,
reversed_by: transaction.reversedBy
};
// Add debit line
if (transaction.amount > 0) {
entry.lines.push({
posting_id: `${entry.entry_id}-1`,
account_code: transaction.debitAccount,
debit: transaction.amount.toFixed(2),
credit: '0.00',
tax_code: transaction.taxCode,
cost_center: transaction.costCenter,
project: transaction.project
});
// Add credit line
entry.lines.push({
posting_id: `${entry.entry_id}-2`,
account_code: transaction.creditAccount,
debit: '0.00',
credit: transaction.amount.toFixed(2)
});
}
// Add VAT lines if applicable
if (transaction.vatAmount && transaction.vatAmount > 0) {
entry.lines.push({
posting_id: `${entry.entry_id}-3`,
account_code: transaction.vatAccount || '1576', // Default VAT account
debit: transaction.vatAmount.toFixed(2),
credit: '0.00',
description: 'Vorsteuer'
});
}
await this.writeLine(entry);
}
/**
* Exports a journal entry
*/
async exportJournalEntry(journalEntry) {
if (!this.stream) {
throw new Error('Ledger exporter not initialized');
}
const entry = {
schema_version: '1.0',
entry_id: journalEntry._id || plugins.smartunique.shortId(),
booking_date: this.formatDate(journalEntry.date),
posting_date: this.formatDate(journalEntry.postingDate || journalEntry.date),
currency: journalEntry.currency || 'EUR',
journal: journalEntry.journal || 'GL',
description: journalEntry.description,
reference: journalEntry.reference,
lines: [],
created_at: journalEntry.createdAt ? new Date(journalEntry.createdAt).toISOString() : new Date().toISOString(),
modified_at: journalEntry.modifiedAt ? new Date(journalEntry.modifiedAt).toISOString() : undefined,
reversal_of: journalEntry.reversalOf,
reversed_by: journalEntry.reversedBy
};
// Convert journal entry lines
journalEntry.lines.forEach((line, index) => {
const extLine = line;
entry.lines.push({
posting_id: `${entry.entry_id}-${index + 1}`,
account_code: line.accountNumber,
debit: (line.debit || 0).toFixed(2),
credit: (line.credit || 0).toFixed(2),
tax_code: extLine.taxCode,
cost_center: line.costCenter,
project: extLine.project,
description: line.description
});
});
await this.writeLine(entry);
}
/**
* Writes a single NDJSON line
*/
async writeLine(entry) {
return new Promise((resolve, reject) => {
if (!this.stream) {
reject(new Error('Stream not initialized'));
return;
}
const line = JSON.stringify(entry) + '\n';
this.stream.write(line, (error) => {
if (error) {
reject(error);
}
else {
this.entryCount++;
resolve();
}
});
});
}
/**
* Formats a date to ISO date string
*/
formatDate(date) {
if (typeof date === 'string') {
return date.split('T')[0];
}
return date.toISOString().split('T')[0];
}
/**
* Closes the export stream
*/
async close() {
return new Promise((resolve) => {
if (this.stream) {
this.stream.end(() => {
resolve(this.entryCount);
});
}
else {
resolve(this.entryCount);
}
});
}
/**
* Gets the number of exported entries
*/
getEntryCount() {
return this.entryCount;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmV4cG9ydC5sZWRnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9za3IuZXhwb3J0LmxlZGdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUU3QixPQUFPLEVBQUUsaUJBQWlCLEVBQW9CLE1BQU0sSUFBSSxDQUFDO0FBcUV6RCxNQUFNLE9BQU8sY0FBYztJQUt6QixZQUFZLFVBQWtCO1FBSHRCLFdBQU0sR0FBdUIsSUFBSSxDQUFDO1FBQ2xDLGVBQVUsR0FBVyxDQUFDLENBQUM7UUFHN0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7SUFDL0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFVBQVU7UUFDckIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDckYsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBRS9ELElBQUksQ0FBQyxNQUFNLEdBQUcsaUJBQWlCLENBQUMsVUFBVSxFQUFFO1lBQzFDLFFBQVEsRUFBRSxNQUFNO1lBQ2hCLEtBQUssRUFBRSxHQUFHO1NBQ1gsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLGlCQUFpQixDQUFDLFdBQW1DO1FBQ2hFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFFRCxNQUFNLEtBQUssR0FBaUI7WUFDMUIsY0FBYyxFQUFFLEtBQUs7WUFDckIsUUFB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