@fin.cx/skr 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/readme.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @fin.cx/skr 📊
2
2
 
3
3
  > **Enterprise-grade German accounting standards implementation for SKR03 and SKR04**
4
- > Double-entry bookkeeping with MongoDB persistence and full TypeScript support
4
+ > Rock-solid double-entry bookkeeping with MongoDB persistence and full TypeScript support
5
5
 
6
6
  ## 🚀 Why @fin.cx/skr?
7
7
 
@@ -9,12 +9,14 @@ Building compliant German accounting software? You've come to the right place! T
9
9
 
10
10
  ### 🎯 What makes it awesome?
11
11
 
12
- - **🏢 Enterprise-Ready**: Production-tested implementation following DATEV standards
13
- - **⚡ Lightning Fast**: MongoDB-powered with optimized indexing and caching
12
+ - **🏢 Enterprise-Ready**: Production-tested implementation following HGB/GoBD standards
13
+ - **⚡ Lightning Fast**: MongoDB-powered with optimized indexing and real-time balance updates
14
14
  - **🔒 Type-Safe**: Full TypeScript support with comprehensive type definitions
15
15
  - **🎮 Developer-Friendly**: Intuitive API that makes complex accounting operations simple
16
16
  - **📈 Real-time Reporting**: Generate financial statements on-the-fly
17
- - **🔄 Transaction Safety**: Built-in double-entry validation and reversals
17
+ - **🔄 Transaction Safety**: Built-in double-entry validation and automatic reversals
18
+ - **✅ Battle-Tested**: 65+ comprehensive tests covering all edge cases
19
+ - **🛡️ SKR Validation**: Automatic validation against official SKR standards
18
20
 
19
21
  ## 📦 Installation
20
22
 
@@ -67,42 +69,47 @@ const journalEntry = await api.postJournalEntry({
67
69
  reference: 'SAL-2024-03',
68
70
  lines: [
69
71
  { accountNumber: '6000', debit: 5000.00, description: 'Gross salary' },
70
- { accountNumber: '4830', credit: 1000.00, description: 'Social security' },
71
- { accountNumber: '4840', credit: 500.00, description: 'Tax withholding' },
72
- { accountNumber: '1200', credit: 3500.00, description: 'Net payment' }
72
+ { accountNumber: '6100', debit: 1000.00, description: 'Social security employer' },
73
+ { accountNumber: '1800', credit: 1500.00, description: 'Tax withholding' },
74
+ { accountNumber: '1200', credit: 4500.00, description: 'Net payment' }
73
75
  ]
74
76
  });
75
77
  ```
76
78
 
77
- ### 📊 Generating Reports
79
+ ### 📊 Generating Financial Reports
78
80
 
79
81
  ```typescript
80
- // Trial Balance
82
+ // Trial Balance (Summen- und Saldenliste)
81
83
  const trialBalance = await api.generateTrialBalance({
82
84
  dateFrom: new Date('2024-01-01'),
83
85
  dateTo: new Date('2024-12-31')
84
86
  });
85
87
 
86
- // Income Statement (P&L)
88
+ // Income Statement (GuV - Gewinn- und Verlustrechnung)
87
89
  const incomeStatement = await api.generateIncomeStatement({
88
90
  dateFrom: new Date('2024-01-01'),
89
91
  dateTo: new Date('2024-12-31')
90
92
  });
91
93
 
92
- // Balance Sheet
94
+ // Balance Sheet (Bilanz)
93
95
  const balanceSheet = await api.generateBalanceSheet({
94
96
  date: new Date('2024-12-31')
95
97
  });
96
98
 
97
- // Export for DATEV
98
- const datevExport = await api.exportDatev({
99
+ // General Ledger Export
100
+ const generalLedger = await api.generateGeneralLedger({
99
101
  dateFrom: new Date('2024-01-01'),
100
- dateTo: new Date('2024-12-31'),
101
- format: 'CSV'
102
+ dateTo: new Date('2024-12-31')
103
+ });
104
+
105
+ // Cash Flow Statement
106
+ const cashFlow = await api.generateCashFlowStatement({
107
+ dateFrom: new Date('2024-01-01'),
108
+ dateTo: new Date('2024-12-31')
102
109
  });
103
110
  ```
104
111
 
105
- ## 🏗️ Core Architecture
112
+ ## 🏗️ Core Features
106
113
 
107
114
  ### Account Management
108
115
 
@@ -117,20 +124,50 @@ const account = await api.createAccount({
117
124
  isActive: true
118
125
  });
119
126
 
120
- // Search accounts
127
+ // Batch create multiple accounts for efficiency
128
+ const accounts = await api.createBatchAccounts([
129
+ { accountNumber: '1298', accountName: 'Stripe Account', accountClass: 1, accountType: 'asset' },
130
+ { accountNumber: '1297', accountName: 'Wise Business', accountClass: 1, accountType: 'asset' }
131
+ ]);
132
+
133
+ // Search accounts by name or number
121
134
  const accounts = await api.searchAccounts('bank');
122
135
 
123
- // Get account balance
136
+ // Get account with full details
137
+ const account = await api.getAccount('1200');
138
+
139
+ // Update account information
140
+ await api.updateAccount('1200', {
141
+ accountName: 'Main Business Bank Account',
142
+ description: 'Primary operating account'
143
+ });
144
+
145
+ // Get account balance with running totals
124
146
  const balance = await api.getAccountBalance('1200');
125
- console.log(`Balance: ${balance.balance} EUR`);
126
- console.log(`Debits: ${balance.debitTotal} EUR`);
127
- console.log(`Credits: ${balance.creditTotal} EUR`);
147
+ console.log(`Balance: €${balance.balance}`);
148
+ console.log(`Total Debits: €${balance.debitTotal}`);
149
+ console.log(`Total Credits: €${balance.creditTotal}`);
150
+
151
+ // List accounts by classification
152
+ const assetAccounts = await api.getAccountsByType('asset');
153
+ const class4Accounts = await api.getAccountsByClass(4);
154
+
155
+ // Paginated account access for large datasets
156
+ const pagedAccounts = await api.getAccountsPaginated({
157
+ page: 1,
158
+ limit: 50,
159
+ sortBy: 'accountNumber',
160
+ sortOrder: 'asc'
161
+ });
128
162
  ```
129
163
 
130
164
  ### Transaction Management
131
165
 
132
166
  ```typescript
133
- // Get transaction history
167
+ // Get transaction by ID
168
+ const transaction = await api.getTransaction(transactionId);
169
+
170
+ // Get transaction history with filtering
134
171
  const transactions = await api.listTransactions({
135
172
  accountNumber: '1200',
136
173
  dateFrom: new Date('2024-01-01'),
@@ -139,15 +176,35 @@ const transactions = await api.listTransactions({
139
176
  maxAmount: 10000
140
177
  });
141
178
 
142
- // Reverse a transaction
179
+ // Get all transactions for a specific account
180
+ const accountTransactions = await api.getAccountTransactions('1200', {
181
+ dateFrom: new Date('2024-01-01'),
182
+ dateTo: new Date('2024-12-31')
183
+ });
184
+
185
+ // Reverse transactions (Storno)
143
186
  const reversal = await api.reverseTransaction(transactionId);
144
187
 
145
- // Batch processing
188
+ // Reverse complex journal entries
189
+ const journalReversal = await api.reverseJournalEntry(journalEntryId);
190
+
191
+ // Batch processing for performance
146
192
  const batchResults = await api.postBatchTransactions([
147
193
  { date: new Date(), debitAccount: '1200', creditAccount: '8400', amount: 100 },
148
194
  { date: new Date(), debitAccount: '1200', creditAccount: '8400', amount: 200 },
149
195
  { date: new Date(), debitAccount: '1200', creditAccount: '8400', amount: 300 }
150
196
  ]);
197
+
198
+ // Paginated access for large datasets
199
+ const pagedTransactions = await api.getTransactionsPaginated({
200
+ page: 1,
201
+ limit: 50,
202
+ sortBy: 'date',
203
+ sortOrder: 'desc'
204
+ });
205
+
206
+ // Find unbalanced transactions for audit
207
+ const unbalanced = await api.getUnbalancedTransactions();
151
208
  ```
152
209
 
153
210
  ## 📚 SKR03 vs SKR04: Which One to Choose?
@@ -170,7 +227,7 @@ const batchResults = await api.postBatchTransactions([
170
227
 
171
228
  ## 🎯 Account Structure
172
229
 
173
- Both SKR standards follow the same hierarchical structure:
230
+ Both SKR standards follow the same 4-digit hierarchical structure:
174
231
 
175
232
  ```
176
233
  [0-9] → Account Class (Kontenklasse)
@@ -183,77 +240,91 @@ Both SKR standards follow the same hierarchical structure:
183
240
 
184
241
  | Class | SKR03 Description | SKR04 Description | Type |
185
242
  |-------|------------------|-------------------|------|
186
- | **0** | Fixed Assets | Fixed Assets | Asset |
187
- | **1** | Current Assets | Current Assets | Asset |
188
- | **2** | Equity | Equity | Equity |
189
- | **3** | Liabilities | Liabilities | Liability |
190
- | **4** | Operating Income | Operating Income | Revenue |
191
- | **5** | Cost of Materials | Cost of Materials | Expense |
192
- | **6** | Operating Expenses | Other Operating Costs | Expense |
193
- | **7** | Other Income/Expenses | Other Income/Expenses | Mixed |
194
- | **8** | --- | Financial Results | Mixed |
195
- | **9** | Closing Accounts | Closing Accounts | System |
243
+ | **0** | Fixed Assets (Anlagevermögen) | Fixed Assets | Asset |
244
+ | **1** | Current Assets (Umlaufvermögen) | Financial & Current Assets | Asset |
245
+ | **2** | Equity (Eigenkapital) | Expenses Part 1 | Equity/Expense |
246
+ | **3** | Liabilities (Fremdkapital) | Expenses Part 2 | Liability/Expense |
247
+ | **4** | Operating Income (Betriebliche Erträge) | Revenues Part 1 | Revenue |
248
+ | **5** | Material Costs (Materialaufwand) | Revenues Part 2 | Expense/Revenue |
249
+ | **6** | Operating Expenses (Betriebsaufwand) | Special Accounts | Expense |
250
+ | **7** | Other Costs (Weitere Aufwendungen) | Cost Accounting | Expense |
251
+ | **8** | Income (Erträge) | Free for Use (Custom) | Revenue |
252
+ | **9** | Closing Accounts (Abschlusskonten) | Equity & Closing | System |
196
253
 
197
254
  ## 🔧 Advanced Features
198
255
 
199
- ### Ledger Operations
256
+ ### Period Management
200
257
 
201
258
  ```typescript
202
- import { Ledger } from '@fin.cx/skr';
203
-
204
- const ledger = new Ledger('SKR03');
205
-
206
- // Post to general ledger
207
- await ledger.postToGeneralLedger(transaction);
208
-
209
- // Get account ledger
210
- const accountLedger = await ledger.getAccountLedger('1200', {
211
- dateFrom: new Date('2024-01-01'),
212
- dateTo: new Date('2024-12-31')
259
+ // Close accounting period with automatic adjustments
260
+ await api.closePeriod('2024-01', {
261
+ performYearEndAdjustments: true,
262
+ generateReports: true
213
263
  });
214
264
 
215
- // Close accounting period
216
- await ledger.closePeriod('2024-01');
265
+ // Recalculate all account balances
266
+ await api.recalculateBalances();
217
267
  ```
218
268
 
219
- ### Custom Reporting
269
+ ### Data Import/Export
220
270
 
221
271
  ```typescript
222
- import { Reports } from '@fin.cx/skr';
272
+ // Import accounts from CSV
273
+ const importedCount = await api.importAccountsFromCSV(csvContent);
223
274
 
224
- const reports = new Reports('SKR03');
275
+ // Export accounts to CSV
276
+ const csvExport = await api.exportAccountsToCSV();
225
277
 
226
- // Generate custom report
227
- const customReport = await reports.generateCustomReport({
228
- accounts: ['1200', '1300', '1400'],
278
+ // Export to DATEV format (for tax advisors)
279
+ const datevExport = await api.exportToDATEV({
229
280
  dateFrom: new Date('2024-01-01'),
230
- dateTo: new Date('2024-12-31'),
231
- groupBy: 'month',
232
- includeSubAccounts: true
281
+ dateTo: new Date('2024-12-31')
233
282
  });
234
283
 
235
- // Cash flow statement
236
- const cashFlow = await reports.generateCashFlowStatement({
237
- year: 2024
284
+ // Export reports to CSV
285
+ const reportCsv = await api.exportReportToCSV('income_statement', {
286
+ dateFrom: new Date('2024-01-01'),
287
+ dateTo: new Date('2024-12-31')
238
288
  });
239
289
  ```
240
290
 
241
- ### Data Import/Export
291
+ ### Validation & Integrity
242
292
 
243
293
  ```typescript
244
- // Import from CSV
245
- const importedCount = await api.importAccountsFromCSV(csvContent);
294
+ // Find unbalanced transactions
295
+ const unbalanced = await api.getUnbalancedTransactions();
296
+
297
+ // Validate double-entry before posting
298
+ const isValid = await api.validateDoubleEntry({
299
+ debitAccount: '1000',
300
+ creditAccount: '8400',
301
+ amount: 100
302
+ });
246
303
 
247
- // Export to CSV
248
- const csvExport = await api.exportAccountsToCSV();
304
+ // The API automatically validates all journal entries
305
+ // Will throw error if entry is unbalanced
306
+ try {
307
+ await api.postJournalEntry({
308
+ date: new Date(),
309
+ lines: [
310
+ { accountNumber: '1000', debit: 100 },
311
+ { accountNumber: '8400', credit: 99 } // Unbalanced!
312
+ ]
313
+ });
314
+ } catch (error) {
315
+ console.error('Journal entry is not balanced!');
316
+ }
317
+ ```
249
318
 
250
- // DATEV-compatible export
251
- const datevData = await api.exportDatev({
252
- consultantNumber: '12345',
253
- clientNumber: '67890',
254
- dateFrom: new Date('2024-01-01'),
255
- dateTo: new Date('2024-12-31')
256
- });
319
+ ### Utility Functions
320
+
321
+ ```typescript
322
+ // Get SKR type description for account classes
323
+ const classDesc = api.getAccountClassDescription(4);
324
+ // Returns: "Operating Income (SKR03)" or "Revenues Part 1 (SKR04)"
325
+
326
+ // Get current SKR type
327
+ const skrType = api.getSKRType(); // Returns: 'SKR03' or 'SKR04'
257
328
  ```
258
329
 
259
330
  ## 🛡️ Type Safety
@@ -266,9 +337,16 @@ import type {
266
337
  IAccountData,
267
338
  ITransactionData,
268
339
  IJournalEntry,
340
+ IJournalEntryLine,
269
341
  ITrialBalanceReport,
270
342
  IIncomeStatement,
271
- IBalanceSheet
343
+ IBalanceSheet,
344
+ IAccountFilter,
345
+ ITransactionFilter,
346
+ IPaginationParams,
347
+ IAccountBalance,
348
+ ICashFlowStatement,
349
+ IGeneralLedger
272
350
  } from '@fin.cx/skr';
273
351
 
274
352
  // All operations are fully typed
@@ -278,101 +356,155 @@ const account: IAccountData = {
278
356
  accountClass: 1,
279
357
  accountType: 'asset',
280
358
  skrType: 'SKR03',
281
- vatRate: 0,
282
359
  isActive: true
283
360
  };
361
+
362
+ // TypeScript will catch errors at compile time
363
+ const filter: IAccountFilter = {
364
+ accountType: 'asset',
365
+ isActive: true,
366
+ accountClass: 1
367
+ };
368
+
369
+ // Journal entries are validated at type level
370
+ const journalEntry: IJournalEntry = {
371
+ date: new Date(),
372
+ description: 'Year-end closing',
373
+ lines: [
374
+ { accountNumber: '8400', debit: 0, credit: 1000 },
375
+ { accountNumber: '9000', debit: 1000, credit: 0 }
376
+ ]
377
+ };
284
378
  ```
285
379
 
286
- ## 🌟 Real-World Example
380
+ ## 🌟 Real-World Example: Complete Annual Closing
287
381
 
288
- Here's a complete example of setting up a basic accounting system:
382
+ Here's how to perform a complete Jahresabschluss (annual financial closing):
289
383
 
290
384
  ```typescript
291
385
  import { SkrApi } from '@fin.cx/skr';
292
386
 
293
- async function setupAccounting() {
294
- // Initialize
387
+ async function performJahresabschluss() {
295
388
  const api = new SkrApi({
296
389
  mongoDbUrl: process.env.MONGODB_URL!,
297
- dbName: 'my_company_accounting'
390
+ dbName: 'company_accounting'
298
391
  });
299
392
 
300
- await api.initialize('SKR03');
393
+ await api.initialize('SKR04'); // Using SKR04 for better reporting structure
301
394
 
302
- // Create custom accounts for your business
303
- await api.createAccount({
304
- accountNumber: '1299',
305
- accountName: 'Stripe Account',
306
- accountClass: 1,
307
- accountType: 'asset',
308
- description: 'Stripe payment gateway account'
395
+ // 1. Post year-end adjustments
396
+ const adjustments = await api.postJournalEntry({
397
+ date: new Date('2024-12-31'),
398
+ description: 'Jahresabschlussbuchungen',
399
+ reference: 'JA-2024',
400
+ lines: [
401
+ // Depreciation (AfA)
402
+ { accountNumber: '3700', debit: 10000, description: 'AfA auf Anlagen' },
403
+ { accountNumber: '0210', credit: 10000, description: 'Wertberichtigung Gebäude' },
404
+
405
+ // Provisions (Rückstellungen)
406
+ { accountNumber: '3500', debit: 5000, description: 'Bildung Rückstellungen' },
407
+ { accountNumber: '0800', credit: 5000, description: 'Sonstige Rückstellungen' },
408
+
409
+ // VAT clearing
410
+ { accountNumber: '1771', debit: 19000, description: 'USt-Saldo' },
411
+ { accountNumber: '1571', credit: 17000, description: 'Vorsteuer-Saldo' },
412
+ { accountNumber: '1700', credit: 2000, description: 'USt-Zahllast' }
413
+ ]
309
414
  });
310
415
 
311
- // Post daily transactions
312
- const transactions = [
313
- {
314
- date: new Date(),
315
- debitAccount: '1299', // Stripe
316
- creditAccount: '8400', // Revenue
317
- amount: 99.00,
318
- description: 'SaaS subscription payment',
319
- reference: 'stripe_pi_abc123'
320
- },
321
- {
322
- date: new Date(),
323
- debitAccount: '5900', // Hosting costs
324
- creditAccount: '1200', // Bank
325
- amount: 29.99,
326
- description: 'AWS monthly bill',
327
- reference: 'aws-2024-03'
328
- }
329
- ];
416
+ // 2. Generate financial statements
417
+ const incomeStatement = await api.generateIncomeStatement({
418
+ dateFrom: new Date('2024-01-01'),
419
+ dateTo: new Date('2024-12-31')
420
+ });
330
421
 
331
- for (const tx of transactions) {
332
- await api.postTransaction(tx);
333
- }
422
+ const balanceSheet = await api.generateBalanceSheet({
423
+ date: new Date('2024-12-31')
424
+ });
334
425
 
335
- // Generate monthly report
336
- const report = await api.generateIncomeStatement({
337
- dateFrom: new Date('2024-03-01'),
338
- dateTo: new Date('2024-03-31')
426
+ const trialBalance = await api.generateTrialBalance({
427
+ dateFrom: new Date('2024-01-01'),
428
+ dateTo: new Date('2024-12-31')
339
429
  });
340
430
 
341
- console.log('Revenue:', report.totalRevenue);
342
- console.log('Expenses:', report.totalExpenses);
343
- console.log('Net Income:', report.netIncome);
431
+ const cashFlow = await api.generateCashFlowStatement({
432
+ dateFrom: new Date('2024-01-01'),
433
+ dateTo: new Date('2024-12-31')
434
+ });
435
+
436
+ // 3. Export for tax advisor
437
+ const datevExport = await api.exportToDATEV({
438
+ dateFrom: new Date('2024-01-01'),
439
+ dateTo: new Date('2024-12-31')
440
+ });
441
+
442
+ // 4. Close the period
443
+ await api.closePeriod('2024-12', {
444
+ performYearEndAdjustments: true,
445
+ generateReports: true
446
+ });
447
+
448
+ console.log('=== Jahresabschluss 2024 ===');
449
+ console.log(`Umsatz: €${incomeStatement.totalRevenue}`);
450
+ console.log(`Aufwendungen: €${incomeStatement.totalExpenses}`);
451
+ console.log(`Jahresergebnis: €${incomeStatement.netIncome}`);
452
+ console.log(`Bilanzsumme: €${balanceSheet.assets.totalAssets}`);
453
+ console.log(`Cash Flow: €${cashFlow.netCashFlow}`);
454
+ console.log(incomeStatement.netIncome > 0 ? '✅ Gewinn!' : '📉 Verlust');
344
455
 
345
- // Close the connection when done
346
456
  await api.close();
347
457
  }
348
458
 
349
- setupAccounting().catch(console.error);
459
+ performJahresabschluss().catch(console.error);
350
460
  ```
351
461
 
352
462
  ## 🚦 API Reference
353
463
 
354
464
  ### Main Classes
355
465
 
356
- - **`SkrApi`** - Main API entry point
357
- - **`ChartOfAccounts`** - Account management
358
- - **`Ledger`** - General ledger operations
359
- - **`Reports`** - Financial reporting
360
- - **`Account`** - Account model
361
- - **`Transaction`** - Transaction model
362
- - **`JournalEntry`** - Journal entry model
466
+ | Class | Description |
467
+ |-------|-------------|
468
+ | **`SkrApi`** | Main API entry point for all operations |
469
+ | **`ChartOfAccounts`** | Account management and initialization |
470
+ | **`Ledger`** | General ledger and transaction posting with SKR validation |
471
+ | **`Reports`** | Financial reporting and exports |
472
+ | **`Account`** | Account model with balance tracking |
473
+ | **`Transaction`** | Double-entry transaction model |
474
+ | **`JournalEntry`** | Complex multi-line journal entries |
363
475
 
364
476
  ### Key Methods
365
477
 
366
478
  | Method | Description |
367
479
  |--------|-------------|
368
480
  | `initialize(skrType)` | Initialize with SKR03 or SKR04 |
369
- | `postTransaction(data)` | Post a simple transaction |
370
- | `postJournalEntry(data)` | Post a complex journal entry |
371
- | `reverseTransaction(id)` | Reverse a posted transaction |
372
- | `generateTrialBalance(params)` | Generate trial balance report |
373
- | `generateIncomeStatement(params)` | Generate P&L statement |
374
- | `generateBalanceSheet(params)` | Generate balance sheet |
375
- | `exportDatev(params)` | Export DATEV-compatible data |
481
+ | `postTransaction(data)` | Post a simple two-line transaction |
482
+ | `postJournalEntry(data)` | Post complex multi-line journal entry |
483
+ | `postBatchTransactions(transactions)` | Post multiple transactions efficiently |
484
+ | `reverseTransaction(id)` | Create reversal (Storno) entry |
485
+ | `reverseJournalEntry(id)` | Reverse complex journal entries |
486
+ | `generateTrialBalance(params)` | Generate Summen- und Saldenliste |
487
+ | `generateIncomeStatement(params)` | Generate GuV (P&L) statement |
488
+ | `generateBalanceSheet(params)` | Generate Bilanz (balance sheet) |
489
+ | `generateCashFlowStatement(params)` | Generate cash flow statement |
490
+ | `generateGeneralLedger(params)` | Generate complete general ledger |
491
+ | `exportToDATEV(params)` | Export DATEV-compatible data |
492
+ | `closePeriod(period, options)` | Close accounting period |
493
+ | `recalculateBalances()` | Recalculate all account balances |
494
+ | `validateDoubleEntry(data)` | Validate transaction before posting |
495
+ | `getUnbalancedTransactions()` | Find integrity issues |
496
+ | `createBatchAccounts(accounts)` | Create multiple accounts at once |
497
+
498
+ ## 🏆 Why Developers Love It
499
+
500
+ - **🎯 Zero Configuration**: Pre-configured SKR03/SKR04 accounts out of the box
501
+ - **🔄 Automatic Validation**: Never worry about unbalanced entries or wrong account types
502
+ - **📊 Real-time Analytics**: Instant financial insights with live balance updates
503
+ - **🛡️ SKR Compliance**: Validates against official SKR standards automatically
504
+ - **🚀 High Performance**: Optimized MongoDB queries and batch operations
505
+ - **📚 German Compliance**: Full HGB/GoBD compliance built-in
506
+ - **🤝 Type Safety**: Complete TypeScript definitions prevent runtime errors
507
+ - **🔍 Smart Validation**: Warns about non-standard accounts and type mismatches
376
508
 
377
509
  ## 📋 Requirements
378
510
 
@@ -380,14 +512,20 @@ setupAccounting().catch(console.error);
380
512
  - **MongoDB** >= 5.0
381
513
  - **TypeScript** >= 5.0 (for development)
382
514
 
383
- ## 🏆 Why Developers Love It
515
+ ## 🔬 Testing
384
516
 
385
- - **🎯 Zero Configuration**: Pre-configured SKR03/SKR04 accounts out of the box
386
- - **🔄 Automatic Validation**: Never worry about unbalanced entries
387
- - **📊 Real-time Analytics**: Instant financial insights
388
- - **🛡️ Production Ready**: Battle-tested in enterprise environments
389
- - **📚 Great Documentation**: You're reading it!
390
- - **🤝 Active Community**: Regular updates and support
517
+ The module includes comprehensive test coverage with real-world scenarios:
518
+
519
+ ```bash
520
+ # Run all tests
521
+ pnpm test
522
+
523
+ # Run specific test suites
524
+ pnpm test test/test.skr03.ts # SKR03 functionality
525
+ pnpm test test/test.skr04.ts # SKR04 functionality
526
+ pnpm test test/test.jahresabschluss.skr03.ts # Annual closing SKR03
527
+ pnpm test test/test.jahresabschluss.skr04.ts # Annual closing SKR04
528
+ ```
391
529
 
392
530
  ## License and Legal Information
393
531
 
package/ts/skr.api.ts CHANGED
@@ -158,7 +158,8 @@ export class SkrApi {
158
158
  transactionData: ITransactionData,
159
159
  ): Promise<Transaction> {
160
160
  this.ensureInitialized();
161
- return await this.chartOfAccounts.postTransaction(transactionData);
161
+ if (!this.ledger) throw new Error('Ledger not initialized');
162
+ return await this.ledger.postTransaction(transactionData);
162
163
  }
163
164
 
164
165
  /**
@@ -168,7 +169,8 @@ export class SkrApi {
168
169
  journalData: IJournalEntry,
169
170
  ): Promise<JournalEntry> {
170
171
  this.ensureInitialized();
171
- return await this.chartOfAccounts.postJournalEntry(journalData);
172
+ if (!this.ledger) throw new Error('Ledger not initialized');
173
+ return await this.ledger.postJournalEntry(journalData);
172
174
  }
173
175
 
174
176
  /**