@fin.cx/skr
Version:
SKR03 and SKR04 German accounting standards for double-entry bookkeeping
548 lines • 48.7 kB
JavaScript
import * as plugins from './plugins.js';
import { Account } from './skr.classes.account.js';
import { Transaction } from './skr.classes.transaction.js';
import { Ledger } from './skr.classes.ledger.js';
export class Reports {
constructor(skrType) {
this.skrType = skrType;
this.logger = new plugins.smartlog.Smartlog({
logContext: {
company: 'fin.cx',
companyunit: 'skr',
containerName: 'Reports',
environment: 'local',
runtime: 'node',
zone: 'local',
},
});
this.ledger = new Ledger(skrType);
}
/**
* Generate Trial Balance
*/
async getTrialBalance(params) {
this.logger.log('info', 'Generating trial balance');
const accounts = await Account.getInstances({
skrType: this.skrType,
isActive: true,
});
const entries = [];
let totalDebits = 0;
let totalCredits = 0;
for (const account of accounts) {
// Get balance for the period if specified
const balance = params?.dateTo
? await this.ledger.getAccountBalance(account.accountNumber, params.dateTo)
: await this.ledger.getAccountBalance(account.accountNumber);
if (balance.debitTotal !== 0 || balance.creditTotal !== 0) {
const entry = {
accountNumber: account.accountNumber,
accountName: account.accountName,
debitBalance: balance.debitTotal,
creditBalance: balance.creditTotal,
netBalance: balance.balance,
};
entries.push(entry);
totalDebits += balance.debitTotal;
totalCredits += balance.creditTotal;
}
}
// Sort entries by account number
entries.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
const report = {
date: params?.dateTo || new Date(),
skrType: this.skrType,
entries,
totalDebits,
totalCredits,
isBalanced: Math.abs(totalDebits - totalCredits) < 0.01,
};
this.logger.log('info', `Trial balance generated with ${entries.length} accounts`);
return report;
}
/**
* Generate Income Statement (P&L)
*/
async getIncomeStatement(params) {
this.logger.log('info', 'Generating income statement');
// Get revenue accounts
const revenueAccounts = await Account.getAccountsByType('revenue', this.skrType);
const expenseAccounts = await Account.getAccountsByType('expense', this.skrType);
const revenueEntries = [];
const expenseEntries = [];
let totalRevenue = 0;
let totalExpenses = 0;
// Process revenue accounts
for (const account of revenueAccounts) {
const balance = await this.getAccountBalanceForPeriod(account, params);
if (balance !== 0) {
const entry = {
accountNumber: account.accountNumber,
accountName: account.accountName,
amount: balance, // Keep the sign for correct calculation
};
revenueEntries.push(entry);
totalRevenue += balance; // Revenue accounts normally have credit balance (positive)
}
}
// Process expense accounts
for (const account of expenseAccounts) {
const balance = await this.getAccountBalanceForPeriod(account, params);
if (balance !== 0) {
const entry = {
accountNumber: account.accountNumber,
accountName: account.accountName,
amount: balance, // Keep the sign - negative balance reduces expenses
};
expenseEntries.push(entry);
totalExpenses += balance; // Expense accounts normally have debit balance (positive)
// But credit balances (negative) reduce total expenses
}
}
// Calculate percentages using absolute values to avoid negative percentages
revenueEntries.forEach((entry) => {
entry.percentage =
totalRevenue !== 0 ? (Math.abs(entry.amount) / Math.abs(totalRevenue)) * 100 : 0;
});
expenseEntries.forEach((entry) => {
entry.percentage =
totalRevenue !== 0 ? (Math.abs(entry.amount) / Math.abs(totalRevenue)) * 100 : 0;
});
// Sort entries by account number
revenueEntries.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
expenseEntries.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
const report = {
date: params?.dateTo || new Date(),
skrType: this.skrType,
revenue: revenueEntries,
expenses: expenseEntries,
totalRevenue,
totalExpenses,
netIncome: totalRevenue - totalExpenses,
};
this.logger.log('info', `Income statement generated: Revenue ${totalRevenue}, Expenses ${totalExpenses}`);
return report;
}
/**
* Generate Balance Sheet
*/
async getBalanceSheet(params) {
this.logger.log('info', 'Generating balance sheet');
// Get accounts by type
const assetAccounts = await Account.getAccountsByType('asset', this.skrType);
const liabilityAccounts = await Account.getAccountsByType('liability', this.skrType);
const equityAccounts = await Account.getAccountsByType('equity', this.skrType);
// Process assets
const currentAssets = [];
const fixedAssets = [];
let totalAssets = 0;
for (const account of assetAccounts) {
const balance = await this.getAccountBalanceForPeriod(account, params);
if (balance !== 0) {
const entry = {
accountNumber: account.accountNumber,
accountName: account.accountName,
amount: balance, // Keep the sign for display
};
// Classify as current or fixed based on account class
if (account.accountClass === 1) {
currentAssets.push(entry);
}
else {
fixedAssets.push(entry);
}
totalAssets += balance; // Add with sign to get correct total
}
}
// Process liabilities
const currentLiabilities = [];
const longTermLiabilities = [];
let totalLiabilities = 0;
for (const account of liabilityAccounts) {
const balance = await this.getAccountBalanceForPeriod(account, params);
if (balance !== 0) {
const entry = {
accountNumber: account.accountNumber,
accountName: account.accountName,
amount: balance, // Keep the sign for display
};
// Classify as current or long-term based on account number
if (account.accountNumber.startsWith('16') ||
account.accountNumber.startsWith('17')) {
currentLiabilities.push(entry);
}
else {
longTermLiabilities.push(entry);
}
totalLiabilities += balance; // Add with sign to get correct total
}
}
// Process equity
const equityEntries = [];
let totalEquity = 0;
for (const account of equityAccounts) {
const balance = await this.getAccountBalanceForPeriod(account, params);
if (balance !== 0) {
const entry = {
accountNumber: account.accountNumber,
accountName: account.accountName,
amount: balance, // Keep the sign for display
};
equityEntries.push(entry);
totalEquity += balance; // Add with sign to get correct total
}
}
// Add current year profit/loss only if accounts haven't been closed
// Check if revenue/expense accounts have non-zero balances (indicates not closed)
const incomeStatement = await this.getIncomeStatement(params);
// Only add current year profit/loss if we have unclosed revenue/expense accounts
// (i.e., the income statement shows non-zero revenue or expenses)
if (incomeStatement.netIncome !== 0 && (incomeStatement.totalRevenue !== 0 || incomeStatement.totalExpenses !== 0)) {
equityEntries.push({
accountNumber: '9999',
accountName: 'Current Year Profit/Loss',
amount: incomeStatement.netIncome, // Keep the sign
});
totalEquity += incomeStatement.netIncome; // Add with sign
}
// Sort entries
currentAssets.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
fixedAssets.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
currentLiabilities.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
longTermLiabilities.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
equityEntries.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
const report = {
date: params?.dateTo || new Date(),
skrType: this.skrType,
assets: {
current: currentAssets,
fixed: fixedAssets,
totalAssets,
},
liabilities: {
current: currentLiabilities,
longTerm: longTermLiabilities,
totalLiabilities,
},
equity: {
entries: equityEntries,
totalEquity,
},
isBalanced: Math.abs(totalAssets - (totalLiabilities + totalEquity)) < 0.01,
};
this.logger.log('info', `Balance sheet generated: Assets ${totalAssets}, Liabilities ${totalLiabilities}, Equity ${totalEquity}`);
return report;
}
/**
* Get account balance for a specific period
*/
async getAccountBalanceForPeriod(account, params) {
let transactions = await Transaction.getTransactionsByAccount(account.accountNumber, this.skrType);
// Apply date filter if provided
if (params?.dateFrom || params?.dateTo) {
// Normalize dates for inclusive comparison
const dateFrom = params.dateFrom ? new Date(params.dateFrom) : null;
const dateTo = params.dateTo ? new Date(params.dateTo) : null;
// Set dateFrom to start of day (00:00:00.000)
if (dateFrom) {
dateFrom.setHours(0, 0, 0, 0);
}
// Set dateTo to end of day (23:59:59.999) for inclusive comparison
if (dateTo) {
dateTo.setHours(23, 59, 59, 999);
}
transactions = transactions.filter((transaction) => {
const txDate = transaction.date instanceof Date
? transaction.date
: new Date(transaction.date);
const txTime = txDate.getTime();
if (dateFrom && txTime < dateFrom.getTime())
return false;
if (dateTo && txTime > dateTo.getTime())
return false;
return true;
});
}
let debitTotal = 0;
let creditTotal = 0;
for (const transaction of transactions) {
if (transaction.debitAccount === account.accountNumber) {
debitTotal += transaction.amount;
}
if (transaction.creditAccount === account.accountNumber) {
creditTotal += transaction.amount;
}
}
// Calculate net balance based on account type
switch (account.accountType) {
case 'asset':
case 'expense':
return debitTotal - creditTotal;
case 'liability':
case 'equity':
case 'revenue':
return creditTotal - debitTotal;
}
}
/**
* Generate General Ledger report
*/
async getGeneralLedger(params) {
this.logger.log('info', 'Generating general ledger');
const accounts = await Account.getInstances({
skrType: this.skrType,
isActive: true,
});
const ledgerEntries = [];
for (const account of accounts) {
const transactions = await this.getAccountTransactions(account.accountNumber, params);
if (transactions.length > 0) {
let runningBalance = 0;
const accountEntries = [];
for (const transaction of transactions) {
const isDebit = transaction.debitAccount === account.accountNumber;
const amount = transaction.amount;
// Update running balance based on account type
if (account.accountType === 'asset' ||
account.accountType === 'expense') {
runningBalance += isDebit ? amount : -amount;
}
else {
runningBalance += isDebit ? -amount : amount;
}
accountEntries.push({
date: transaction.date,
reference: transaction.reference,
description: transaction.description,
debit: isDebit ? amount : 0,
credit: !isDebit ? amount : 0,
balance: runningBalance,
});
}
ledgerEntries.push({
accountNumber: account.accountNumber,
accountName: account.accountName,
accountType: account.accountType,
entries: accountEntries,
finalBalance: runningBalance,
});
}
}
return {
date: params?.dateTo || new Date(),
skrType: this.skrType,
accounts: ledgerEntries,
};
}
/**
* Get account transactions for reporting
*/
async getAccountTransactions(accountNumber, params) {
let transactions = await Transaction.getTransactionsByAccount(accountNumber, this.skrType);
// Apply date filter
if (params?.dateFrom || params?.dateTo) {
// Normalize dates for inclusive comparison
const dateFrom = params.dateFrom ? new Date(params.dateFrom) : null;
const dateTo = params.dateTo ? new Date(params.dateTo) : null;
// Set dateFrom to start of day (00:00:00.000)
if (dateFrom) {
dateFrom.setHours(0, 0, 0, 0);
}
// Set dateTo to end of day (23:59:59.999) for inclusive comparison
if (dateTo) {
dateTo.setHours(23, 59, 59, 999);
}
transactions = transactions.filter((transaction) => {
const txDate = transaction.date instanceof Date
? transaction.date
: new Date(transaction.date);
const txTime = txDate.getTime();
if (dateFrom && txTime < dateFrom.getTime())
return false;
if (dateTo && txTime > dateTo.getTime())
return false;
return true;
});
}
// Sort by date
transactions.sort((a, b) => a.date.getTime() - b.date.getTime());
return transactions;
}
/**
* Generate Cash Flow Statement
*/
async getCashFlowStatement(params) {
this.logger.log('info', 'Generating cash flow statement');
// Get cash and bank accounts
const cashAccounts = ['1000', '1100', '1200', '1210']; // Standard cash/bank accounts
let operatingCashFlow = 0;
let investingCashFlow = 0;
let financingCashFlow = 0;
for (const accountNumber of cashAccounts) {
const account = await Account.getAccountByNumber(accountNumber, this.skrType);
if (!account)
continue;
const transactions = await this.getAccountTransactions(accountNumber, params);
for (const transaction of transactions) {
const otherAccount = transaction.debitAccount === accountNumber
? transaction.creditAccount
: transaction.debitAccount;
const otherAccountObj = await Account.getAccountByNumber(otherAccount, this.skrType);
if (!otherAccountObj)
continue;
const amount = transaction.debitAccount === accountNumber
? transaction.amount
: -transaction.amount;
// Classify cash flow
if (otherAccountObj.accountType === 'revenue' ||
otherAccountObj.accountType === 'expense') {
operatingCashFlow += amount;
}
else if (otherAccountObj.accountClass === 0) {
// Fixed assets
investingCashFlow += amount;
}
else if (otherAccountObj.accountType === 'liability' ||
otherAccountObj.accountType === 'equity') {
financingCashFlow += amount;
}
}
}
return {
date: params?.dateTo || new Date(),
skrType: this.skrType,
operatingActivities: operatingCashFlow,
investingActivities: investingCashFlow,
financingActivities: financingCashFlow,
netCashFlow: operatingCashFlow + investingCashFlow + financingCashFlow,
};
}
/**
* Export report to CSV format
*/
async exportToCSV(reportType, params) {
let csvContent = '';
switch (reportType) {
case 'trial_balance':
const trialBalance = await this.getTrialBalance(params);
csvContent = this.trialBalanceToCSV(trialBalance);
break;
case 'income_statement':
const incomeStatement = await this.getIncomeStatement(params);
csvContent = this.incomeStatementToCSV(incomeStatement);
break;
case 'balance_sheet':
const balanceSheet = await this.getBalanceSheet(params);
csvContent = this.balanceSheetToCSV(balanceSheet);
break;
}
return csvContent;
}
/**
* Convert trial balance to CSV
*/
trialBalanceToCSV(report) {
const lines = [];
lines.push('"Account Number";"Account Name";"Debit";"Credit";"Balance"');
for (const entry of report.entries) {
lines.push(`"${entry.accountNumber}";"${entry.accountName}";${entry.debitBalance};${entry.creditBalance};${entry.netBalance}`);
}
lines.push(`"TOTAL";"";"${report.totalDebits}";"${report.totalCredits}";"""`);
return lines.join('\n');
}
/**
* Convert income statement to CSV
*/
incomeStatementToCSV(report) {
const lines = [];
lines.push('"Type";"Account Number";"Account Name";"Amount";"Percentage"');
lines.push('"REVENUE";"";"";"";""');
for (const entry of report.revenue) {
lines.push(`"Revenue";"${entry.accountNumber}";"${entry.accountName}";${entry.amount};${entry.percentage?.toFixed(2)}%`);
}
lines.push(`"Total Revenue";"";"";"${report.totalRevenue}";"""`);
lines.push('"";"";"";"";""');
lines.push('"EXPENSES";"";"";"";""');
for (const entry of report.expenses) {
lines.push(`"Expense";"${entry.accountNumber}";"${entry.accountName}";${entry.amount};${entry.percentage?.toFixed(2)}%`);
}
lines.push(`"Total Expenses";"";"";"${report.totalExpenses}";"""`);
lines.push('"";"";"";"";""');
lines.push(`"NET INCOME";"";"";"${report.netIncome}";"""`);
return lines.join('\n');
}
/**
* Convert balance sheet to CSV
*/
balanceSheetToCSV(report) {
const lines = [];
lines.push('"Category";"Account Number";"Account Name";"Amount"');
lines.push('"ASSETS";"";"";"";');
lines.push('"Current Assets";"";"";"";');
for (const entry of report.assets.current) {
lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
}
lines.push('"Fixed Assets";"";"";"";');
for (const entry of report.assets.fixed) {
lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
}
lines.push(`"Total Assets";"";"";"${report.assets.totalAssets}"`);
lines.push('"";"";"";"";');
lines.push('"LIABILITIES";"";"";"";');
lines.push('"Current Liabilities";"";"";"";');
for (const entry of report.liabilities.current) {
lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
}
lines.push('"Long-term Liabilities";"";"";"";');
for (const entry of report.liabilities.longTerm) {
lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
}
lines.push(`"Total Liabilities";"";"";"${report.liabilities.totalLiabilities}"`);
lines.push('"";"";"";"";');
lines.push('"EQUITY";"";"";"";');
for (const entry of report.equity.entries) {
lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
}
lines.push(`"Total Equity";"";"";"${report.equity.totalEquity}"`);
lines.push('"";"";"";"";');
lines.push(`"Total Liabilities + Equity";"";"";"${report.liabilities.totalLiabilities + report.equity.totalEquity}"`);
return lines.join('\n');
}
/**
* Export to DATEV format
*/
async exportToDATEV(params) {
// DATEV format is specific to German accounting software
// This is a simplified implementation
const transactions = await Transaction.getInstances({
skrType: this.skrType,
status: 'posted',
});
const lines = [];
// DATEV header
lines.push('EXTF;510;21;"Buchungsstapel";1;;;;;;;;;;;;;;');
for (const transaction of transactions) {
const date = transaction.date
.toISOString()
.split('T')[0]
.replace(/-/g, '');
const line = [
transaction.amount.toFixed(2).replace('.', ','),
'S',
'EUR',
'',
'',
transaction.debitAccount,
transaction.creditAccount,
'',
date,
'',
transaction.description.substring(0, 60),
'',
].join(';');
lines.push(line);
}
return lines.join('\n');
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmNsYXNzZXMucmVwb3J0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3Nrci5jbGFzc2VzLnJlcG9ydHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFZakQsTUFBTSxPQUFPLE9BQU87SUFJbEIsWUFBb0IsT0FBaUI7UUFBakIsWUFBTyxHQUFQLE9BQU8sQ0FBVTtRQUNuQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7WUFDMUMsVUFBVSxFQUFFO2dCQUNWLE9BQU8sRUFBRSxRQUFRO2dCQUNqQixXQUFXLEVBQUUsS0FBSztnQkFDbEIsYUFBYSxFQUFFLFNBQVM7Z0JBQ3hCLFdBQVcsRUFBRSxPQUFPO2dCQUNwQixPQUFPLEVBQUUsTUFBTTtnQkFDZixJQUFJLEVBQUUsT0FBTzthQUNkO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsZUFBZSxDQUMxQixNQUFzQjtRQUV0QixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztRQUVwRCxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFDMUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1lBQ3JCLFFBQVEsRUFBRSxJQUFJO1NBQ2YsQ0FBQyxDQUFDO1FBRUgsTUFBTSxPQUFPLEdBQXlCLEVBQUUsQ0FBQztR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