@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/dist_ts/skr.api.js +7 -3
- package/dist_ts/skr.classes.journalentry.d.ts +1 -0
- package/dist_ts/skr.classes.journalentry.js +55 -15
- package/dist_ts/skr.classes.ledger.d.ts +4 -0
- package/dist_ts/skr.classes.ledger.js +72 -1
- package/dist_ts/skr.classes.reports.js +56 -22
- package/package.json +3 -2
- package/readme.md +278 -140
- package/ts/skr.api.ts +4 -2
- package/ts/skr.classes.journalentry.ts +63 -14
- package/ts/skr.classes.ledger.ts +85 -0
- package/ts/skr.classes.reports.ts +64 -21
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
|
-
>
|
|
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
|
|
13
|
-
- **⚡ Lightning Fast**: MongoDB-powered with optimized indexing and
|
|
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: '
|
|
71
|
-
{ accountNumber: '
|
|
72
|
-
{ accountNumber: '1200', credit:
|
|
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 (
|
|
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
|
-
//
|
|
98
|
-
const
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
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
|
|
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:
|
|
126
|
-
console.log(`Debits:
|
|
127
|
-
console.log(`Credits:
|
|
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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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 |
|
|
189
|
-
| **3** | Liabilities |
|
|
190
|
-
| **4** | Operating Income |
|
|
191
|
-
| **5** |
|
|
192
|
-
| **6** | Operating Expenses |
|
|
193
|
-
| **7** | Other
|
|
194
|
-
| **8** |
|
|
195
|
-
| **9** | Closing Accounts | Closing
|
|
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
|
-
###
|
|
256
|
+
### Period Management
|
|
200
257
|
|
|
201
258
|
```typescript
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
//
|
|
216
|
-
await
|
|
265
|
+
// Recalculate all account balances
|
|
266
|
+
await api.recalculateBalances();
|
|
217
267
|
```
|
|
218
268
|
|
|
219
|
-
###
|
|
269
|
+
### Data Import/Export
|
|
220
270
|
|
|
221
271
|
```typescript
|
|
222
|
-
|
|
272
|
+
// Import accounts from CSV
|
|
273
|
+
const importedCount = await api.importAccountsFromCSV(csvContent);
|
|
223
274
|
|
|
224
|
-
|
|
275
|
+
// Export accounts to CSV
|
|
276
|
+
const csvExport = await api.exportAccountsToCSV();
|
|
225
277
|
|
|
226
|
-
//
|
|
227
|
-
const
|
|
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
|
-
//
|
|
236
|
-
const
|
|
237
|
-
|
|
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
|
-
###
|
|
291
|
+
### Validation & Integrity
|
|
242
292
|
|
|
243
293
|
```typescript
|
|
244
|
-
//
|
|
245
|
-
const
|
|
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
|
-
//
|
|
248
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
|
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
|
|
294
|
-
// Initialize
|
|
387
|
+
async function performJahresabschluss() {
|
|
295
388
|
const api = new SkrApi({
|
|
296
389
|
mongoDbUrl: process.env.MONGODB_URL!,
|
|
297
|
-
dbName: '
|
|
390
|
+
dbName: 'company_accounting'
|
|
298
391
|
});
|
|
299
392
|
|
|
300
|
-
await api.initialize('
|
|
393
|
+
await api.initialize('SKR04'); // Using SKR04 for better reporting structure
|
|
301
394
|
|
|
302
|
-
//
|
|
303
|
-
await api.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
-
//
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
422
|
+
const balanceSheet = await api.generateBalanceSheet({
|
|
423
|
+
date: new Date('2024-12-31')
|
|
424
|
+
});
|
|
334
425
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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
|
-
|
|
459
|
+
performJahresabschluss().catch(console.error);
|
|
350
460
|
```
|
|
351
461
|
|
|
352
462
|
## 🚦 API Reference
|
|
353
463
|
|
|
354
464
|
### Main Classes
|
|
355
465
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
373
|
-
| `
|
|
374
|
-
| `
|
|
375
|
-
| `
|
|
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
|
-
##
|
|
515
|
+
## 🔬 Testing
|
|
384
516
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
-
|
|
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
|
-
|
|
172
|
+
if (!this.ledger) throw new Error('Ledger not initialized');
|
|
173
|
+
return await this.ledger.postJournalEntry(journalData);
|
|
172
174
|
}
|
|
173
175
|
|
|
174
176
|
/**
|