Juergen Kunz 08d7803be2
Some checks failed
Default (tags) / security (push) Successful in 43s
Default (tags) / test (push) Failing after 4m4s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
feat(validation): add SKR standard validation for account compliance
2025-08-11 11:06:49 +00:00
2025-08-10 17:11:53 +00:00
2025-08-10 17:11:53 +00:00

@fin.cx/skr 📊

Enterprise-grade German accounting standards implementation for SKR03 and SKR04
Rock-solid double-entry bookkeeping with MongoDB persistence and full TypeScript support

🚀 Why @fin.cx/skr?

Building compliant German accounting software? You've come to the right place! This module provides a complete, type-safe implementation of the German standard charts of accounts (Standardkontenrahmen) SKR03 and SKR04, the backbone of professional accounting in Germany.

🎯 What makes it awesome?

  • 🏢 Enterprise-Ready: Production-tested implementation following HGB/GoBD standards
  • Lightning Fast: MongoDB-powered with optimized indexing and real-time balance updates
  • 🔒 Type-Safe: Full TypeScript support with comprehensive type definitions
  • 🎮 Developer-Friendly: Intuitive API that makes complex accounting operations simple
  • 📈 Real-time Reporting: Generate financial statements on-the-fly
  • 🔄 Transaction Safety: Built-in double-entry validation and automatic reversals
  • Battle-Tested: 65+ comprehensive tests covering all edge cases
  • 🛡️ SKR Validation: Automatic validation against official SKR standards

📦 Installation

# Using npm
npm install @fin.cx/skr

# Using pnpm (recommended)
pnpm add @fin.cx/skr

# Using yarn
yarn add @fin.cx/skr

🎓 Quick Start

Basic Setup

import { SkrApi } from '@fin.cx/skr';

// Initialize the API
const api = new SkrApi({
  mongoDbUrl: 'mongodb://localhost:27017',
  dbName: 'accounting' // optional, defaults to 'skr_accounting'
});

// Choose your SKR standard (SKR03 or SKR04)
await api.initialize('SKR03');

💰 Posting Transactions

// Simple transaction posting
const transaction = await api.postTransaction({
  date: new Date(),
  debitAccount: '1200',  // Bank account
  creditAccount: '8400', // Revenue account  
  amount: 1190.00,
  description: 'Invoice #2024-001 payment received',
  reference: 'INV-2024-001',
  vatAmount: 190.00
});

// Complex journal entry with multiple lines
const journalEntry = await api.postJournalEntry({
  date: new Date(),
  description: 'Monthly salary payments',
  reference: 'SAL-2024-03',
  lines: [
    { accountNumber: '6000', debit: 5000.00, description: 'Gross salary' },
    { accountNumber: '6100', debit: 1000.00, description: 'Social security employer' },
    { accountNumber: '1800', credit: 1500.00, description: 'Tax withholding' },
    { accountNumber: '1200', credit: 4500.00, description: 'Net payment' }
  ]
});

📊 Generating Financial Reports

// Trial Balance (Summen- und Saldenliste)
const trialBalance = await api.generateTrialBalance({
  dateFrom: new Date('2024-01-01'),
  dateTo: new Date('2024-12-31')
});

// Income Statement (GuV - Gewinn- und Verlustrechnung)
const incomeStatement = await api.generateIncomeStatement({
  dateFrom: new Date('2024-01-01'),
  dateTo: new Date('2024-12-31')
});

// Balance Sheet (Bilanz)
const balanceSheet = await api.generateBalanceSheet({
  date: new Date('2024-12-31')
});

// General Ledger Export
const generalLedger = await api.generateGeneralLedger({
  dateFrom: new Date('2024-01-01'),
  dateTo: new Date('2024-12-31')
});

// Cash Flow Statement
const cashFlow = await api.generateCashFlowStatement({
  dateFrom: new Date('2024-01-01'),
  dateTo: new Date('2024-12-31')
});

🏗️ Core Features

Account Management

// Create custom accounts
const account = await api.createAccount({
  accountNumber: '1299',
  accountName: 'PayPal Business',
  accountClass: 1,
  accountType: 'asset',
  description: 'PayPal business account for online payments',
  isActive: true
});

// Batch create multiple accounts for efficiency
const accounts = await api.createBatchAccounts([
  { accountNumber: '1298', accountName: 'Stripe Account', accountClass: 1, accountType: 'asset' },
  { accountNumber: '1297', accountName: 'Wise Business', accountClass: 1, accountType: 'asset' }
]);

// Search accounts by name or number
const accounts = await api.searchAccounts('bank');

// Get account with full details
const account = await api.getAccount('1200');

// Update account information
await api.updateAccount('1200', {
  accountName: 'Main Business Bank Account',
  description: 'Primary operating account'
});

// Get account balance with running totals
const balance = await api.getAccountBalance('1200');
console.log(`Balance: €${balance.balance}`);
console.log(`Total Debits: €${balance.debitTotal}`);
console.log(`Total Credits: €${balance.creditTotal}`);

// List accounts by classification
const assetAccounts = await api.getAccountsByType('asset');
const class4Accounts = await api.getAccountsByClass(4);

// Paginated account access for large datasets
const pagedAccounts = await api.getAccountsPaginated({
  page: 1,
  limit: 50,
  sortBy: 'accountNumber',
  sortOrder: 'asc'
});

Transaction Management

// Get transaction by ID
const transaction = await api.getTransaction(transactionId);

// Get transaction history with filtering
const transactions = await api.listTransactions({
  accountNumber: '1200',
  dateFrom: new Date('2024-01-01'),
  dateTo: new Date('2024-12-31'),
  minAmount: 100,
  maxAmount: 10000
});

// Get all transactions for a specific account
const accountTransactions = await api.getAccountTransactions('1200', {
  dateFrom: new Date('2024-01-01'),
  dateTo: new Date('2024-12-31')
});

// Reverse transactions (Storno)
const reversal = await api.reverseTransaction(transactionId);

// Reverse complex journal entries
const journalReversal = await api.reverseJournalEntry(journalEntryId);

// Batch processing for performance
const batchResults = await api.postBatchTransactions([
  { date: new Date(), debitAccount: '1200', creditAccount: '8400', amount: 100 },
  { date: new Date(), debitAccount: '1200', creditAccount: '8400', amount: 200 },
  { date: new Date(), debitAccount: '1200', creditAccount: '8400', amount: 300 }
]);

// Paginated access for large datasets
const pagedTransactions = await api.getTransactionsPaginated({
  page: 1,
  limit: 50,
  sortBy: 'date',
  sortOrder: 'desc'
});

// Find unbalanced transactions for audit
const unbalanced = await api.getUnbalancedTransactions();

📚 SKR03 vs SKR04: Which One to Choose?

SKR03 - Process Structure Principle (Prozessgliederungsprinzip)

Best for: 🛍️ Trading companies, 💼 Service providers, 🏪 Retail businesses

  • Accounts organized by business process flow
  • Easier mapping to operational workflows
  • Natural progression from purchasing → inventory → sales
  • Popular with small to medium enterprises

SKR04 - Financial Classification Principle (Abschlussgliederungsprinzip)

Best for: 🏭 Manufacturing companies, 🏗️ Large corporations, 📈 Public companies

  • Accounts organized by financial statement structure
  • Direct mapping to balance sheet and P&L positions
  • Simplified financial reporting and analysis
  • Preferred by auditors and financial institutions

🎯 Account Structure

Both SKR standards follow the same 4-digit hierarchical structure:

[0-9]    → Account Class (Kontenklasse)
 [0-9]   → Account Group (Kontengruppe)
  [0-9]  → Account Subgroup (Kontenuntergruppe)
   [0-9] → Individual Account (Einzelkonto)

Account Classes Overview

Class SKR03 Description SKR04 Description Type
0 Fixed Assets (Anlagevermögen) Fixed Assets Asset
1 Current Assets (Umlaufvermögen) Financial & Current Assets Asset
2 Equity (Eigenkapital) Expenses Part 1 Equity/Expense
3 Liabilities (Fremdkapital) Expenses Part 2 Liability/Expense
4 Operating Income (Betriebliche Erträge) Revenues Part 1 Revenue
5 Material Costs (Materialaufwand) Revenues Part 2 Expense/Revenue
6 Operating Expenses (Betriebsaufwand) Special Accounts Expense
7 Other Costs (Weitere Aufwendungen) Cost Accounting Expense
8 Income (Erträge) Free for Use (Custom) Revenue
9 Closing Accounts (Abschlusskonten) Equity & Closing System

🔧 Advanced Features

Period Management

// Close accounting period with automatic adjustments
await api.closePeriod('2024-01', {
  performYearEndAdjustments: true,
  generateReports: true
});

// Recalculate all account balances
await api.recalculateBalances();

Data Import/Export

// Import accounts from CSV
const importedCount = await api.importAccountsFromCSV(csvContent);

// Export accounts to CSV
const csvExport = await api.exportAccountsToCSV();

// Export to DATEV format (for tax advisors)
const datevExport = await api.exportToDATEV({
  dateFrom: new Date('2024-01-01'),
  dateTo: new Date('2024-12-31')
});

// Export reports to CSV
const reportCsv = await api.exportReportToCSV('income_statement', {
  dateFrom: new Date('2024-01-01'),
  dateTo: new Date('2024-12-31')
});

Validation & Integrity

// Find unbalanced transactions
const unbalanced = await api.getUnbalancedTransactions();

// Validate double-entry before posting
const isValid = await api.validateDoubleEntry({
  debitAccount: '1000',
  creditAccount: '8400',
  amount: 100
});

// The API automatically validates all journal entries
// Will throw error if entry is unbalanced
try {
  await api.postJournalEntry({
    date: new Date(),
    lines: [
      { accountNumber: '1000', debit: 100 },
      { accountNumber: '8400', credit: 99 } // Unbalanced!
    ]
  });
} catch (error) {
  console.error('Journal entry is not balanced!');
}

Utility Functions

// Get SKR type description for account classes
const classDesc = api.getAccountClassDescription(4);
// Returns: "Operating Income (SKR03)" or "Revenues Part 1 (SKR04)"

// Get current SKR type
const skrType = api.getSKRType(); // Returns: 'SKR03' or 'SKR04'

🛡️ Type Safety

Full TypeScript support with comprehensive type definitions:

import type { 
  TSKRType,
  IAccountData,
  ITransactionData,
  IJournalEntry,
  IJournalEntryLine,
  ITrialBalanceReport,
  IIncomeStatement,
  IBalanceSheet,
  IAccountFilter,
  ITransactionFilter,
  IPaginationParams,
  IAccountBalance,
  ICashFlowStatement,
  IGeneralLedger
} from '@fin.cx/skr';

// All operations are fully typed
const account: IAccountData = {
  accountNumber: '1200',
  accountName: 'Bank Account',
  accountClass: 1,
  accountType: 'asset',
  skrType: 'SKR03',
  isActive: true
};

// TypeScript will catch errors at compile time
const filter: IAccountFilter = {
  accountType: 'asset',
  isActive: true,
  accountClass: 1
};

// Journal entries are validated at type level
const journalEntry: IJournalEntry = {
  date: new Date(),
  description: 'Year-end closing',
  lines: [
    { accountNumber: '8400', debit: 0, credit: 1000 },
    { accountNumber: '9000', debit: 1000, credit: 0 }
  ]
};

🌟 Real-World Example: Complete Annual Closing

Here's how to perform a complete Jahresabschluss (annual financial closing):

import { SkrApi } from '@fin.cx/skr';

async function performJahresabschluss() {
  const api = new SkrApi({
    mongoDbUrl: process.env.MONGODB_URL!,
    dbName: 'company_accounting'
  });
  
  await api.initialize('SKR04'); // Using SKR04 for better reporting structure
  
  // 1. Post year-end adjustments
  const adjustments = await api.postJournalEntry({
    date: new Date('2024-12-31'),
    description: 'Jahresabschlussbuchungen',
    reference: 'JA-2024',
    lines: [
      // Depreciation (AfA)
      { accountNumber: '3700', debit: 10000, description: 'AfA auf Anlagen' },
      { accountNumber: '0210', credit: 10000, description: 'Wertberichtigung Gebäude' },
      
      // Provisions (Rückstellungen)
      { accountNumber: '3500', debit: 5000, description: 'Bildung Rückstellungen' },
      { accountNumber: '0800', credit: 5000, description: 'Sonstige Rückstellungen' },
      
      // VAT clearing
      { accountNumber: '1771', debit: 19000, description: 'USt-Saldo' },
      { accountNumber: '1571', credit: 17000, description: 'Vorsteuer-Saldo' },
      { accountNumber: '1700', credit: 2000, description: 'USt-Zahllast' }
    ]
  });
  
  // 2. Generate financial statements
  const incomeStatement = await api.generateIncomeStatement({
    dateFrom: new Date('2024-01-01'),
    dateTo: new Date('2024-12-31')
  });
  
  const balanceSheet = await api.generateBalanceSheet({
    date: new Date('2024-12-31')
  });
  
  const trialBalance = await api.generateTrialBalance({
    dateFrom: new Date('2024-01-01'),
    dateTo: new Date('2024-12-31')
  });
  
  const cashFlow = await api.generateCashFlowStatement({
    dateFrom: new Date('2024-01-01'),
    dateTo: new Date('2024-12-31')
  });
  
  // 3. Export for tax advisor
  const datevExport = await api.exportToDATEV({
    dateFrom: new Date('2024-01-01'),
    dateTo: new Date('2024-12-31')
  });
  
  // 4. Close the period
  await api.closePeriod('2024-12', {
    performYearEndAdjustments: true,
    generateReports: true
  });
  
  console.log('=== Jahresabschluss 2024 ===');
  console.log(`Umsatz: €${incomeStatement.totalRevenue}`);
  console.log(`Aufwendungen: €${incomeStatement.totalExpenses}`);
  console.log(`Jahresergebnis: €${incomeStatement.netIncome}`);
  console.log(`Bilanzsumme: €${balanceSheet.assets.totalAssets}`);
  console.log(`Cash Flow: €${cashFlow.netCashFlow}`);
  console.log(incomeStatement.netIncome > 0 ? '✅ Gewinn!' : '📉 Verlust');
  
  await api.close();
}

performJahresabschluss().catch(console.error);

🚦 API Reference

Main Classes

Class Description
SkrApi Main API entry point for all operations
ChartOfAccounts Account management and initialization
Ledger General ledger and transaction posting with SKR validation
Reports Financial reporting and exports
Account Account model with balance tracking
Transaction Double-entry transaction model
JournalEntry Complex multi-line journal entries

Key Methods

Method Description
initialize(skrType) Initialize with SKR03 or SKR04
postTransaction(data) Post a simple two-line transaction
postJournalEntry(data) Post complex multi-line journal entry
postBatchTransactions(transactions) Post multiple transactions efficiently
reverseTransaction(id) Create reversal (Storno) entry
reverseJournalEntry(id) Reverse complex journal entries
generateTrialBalance(params) Generate Summen- und Saldenliste
generateIncomeStatement(params) Generate GuV (P&L) statement
generateBalanceSheet(params) Generate Bilanz (balance sheet)
generateCashFlowStatement(params) Generate cash flow statement
generateGeneralLedger(params) Generate complete general ledger
exportToDATEV(params) Export DATEV-compatible data
closePeriod(period, options) Close accounting period
recalculateBalances() Recalculate all account balances
validateDoubleEntry(data) Validate transaction before posting
getUnbalancedTransactions() Find integrity issues
createBatchAccounts(accounts) Create multiple accounts at once

🏆 Why Developers Love It

  • 🎯 Zero Configuration: Pre-configured SKR03/SKR04 accounts out of the box
  • 🔄 Automatic Validation: Never worry about unbalanced entries or wrong account types
  • 📊 Real-time Analytics: Instant financial insights with live balance updates
  • 🛡️ SKR Compliance: Validates against official SKR standards automatically
  • 🚀 High Performance: Optimized MongoDB queries and batch operations
  • 📚 German Compliance: Full HGB/GoBD compliance built-in
  • 🤝 Type Safety: Complete TypeScript definitions prevent runtime errors
  • 🔍 Smart Validation: Warns about non-standard accounts and type mismatches

📋 Requirements

  • Node.js >= 18.0.0
  • MongoDB >= 5.0
  • TypeScript >= 5.0 (for development)

🔬 Testing

The module includes comprehensive test coverage with real-world scenarios:

# Run all tests
pnpm test

# Run specific test suites
pnpm test test/test.skr03.ts         # SKR03 functionality
pnpm test test/test.skr04.ts         # SKR04 functionality
pnpm test test/test.jahresabschluss.skr03.ts  # Annual closing SKR03
pnpm test test/test.jahresabschluss.skr04.ts  # Annual closing SKR04

This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the license file within this repository.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.

Company Information

Task Venture Capital GmbH
Registered at District court Bremen HRB 35230 HB, Germany

For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

Description
a module implementing german SKR03/SKR04 account structures.
Readme 540 KiB
Languages
TypeScript 93.8%
Shell 6.2%