@fin.cx/skr 1.0.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.
Files changed (44) hide show
  1. package/dist_ts/index.d.ts +10 -0
  2. package/dist_ts/index.js +11 -0
  3. package/dist_ts/plugins.d.ts +5 -0
  4. package/dist_ts/plugins.js +7 -0
  5. package/dist_ts/skr.api.d.ts +181 -0
  6. package/dist_ts/skr.api.js +402 -0
  7. package/dist_ts/skr.classes.account.d.ts +34 -0
  8. package/dist_ts/skr.classes.account.js +224 -0
  9. package/dist_ts/skr.classes.chartofaccounts.d.ts +99 -0
  10. package/dist_ts/skr.classes.chartofaccounts.js +377 -0
  11. package/dist_ts/skr.classes.journalentry.d.ts +33 -0
  12. package/dist_ts/skr.classes.journalentry.js +296 -0
  13. package/dist_ts/skr.classes.ledger.d.ts +61 -0
  14. package/dist_ts/skr.classes.ledger.js +363 -0
  15. package/dist_ts/skr.classes.reports.d.ts +55 -0
  16. package/dist_ts/skr.classes.reports.js +514 -0
  17. package/dist_ts/skr.classes.transaction.d.ts +37 -0
  18. package/dist_ts/skr.classes.transaction.js +263 -0
  19. package/dist_ts/skr.database.d.ts +5 -0
  20. package/dist_ts/skr.database.js +28 -0
  21. package/dist_ts/skr.types.d.ts +126 -0
  22. package/dist_ts/skr.types.js +2 -0
  23. package/dist_ts/skr03.data.d.ts +18 -0
  24. package/dist_ts/skr03.data.js +890 -0
  25. package/dist_ts/skr04.data.d.ts +18 -0
  26. package/dist_ts/skr04.data.js +912 -0
  27. package/npmextra.json +17 -0
  28. package/package.json +61 -0
  29. package/readme.hints.md +3 -0
  30. package/readme.md +409 -0
  31. package/readme.plan.md +243 -0
  32. package/ts/index.ts +10 -0
  33. package/ts/plugins.ts +7 -0
  34. package/ts/skr.api.ts +533 -0
  35. package/ts/skr.classes.account.ts +238 -0
  36. package/ts/skr.classes.chartofaccounts.ts +508 -0
  37. package/ts/skr.classes.journalentry.ts +318 -0
  38. package/ts/skr.classes.ledger.ts +528 -0
  39. package/ts/skr.classes.reports.ts +721 -0
  40. package/ts/skr.classes.transaction.ts +300 -0
  41. package/ts/skr.database.ts +39 -0
  42. package/ts/skr.types.ts +154 -0
  43. package/ts/skr03.data.ts +901 -0
  44. package/ts/skr04.data.ts +923 -0
@@ -0,0 +1,514 @@
1
+ import * as plugins from './plugins.js';
2
+ import { Account } from './skr.classes.account.js';
3
+ import { Transaction } from './skr.classes.transaction.js';
4
+ import { Ledger } from './skr.classes.ledger.js';
5
+ export class Reports {
6
+ constructor(skrType) {
7
+ this.skrType = skrType;
8
+ this.logger = new plugins.smartlog.Smartlog({
9
+ logContext: {
10
+ company: 'fin.cx',
11
+ companyunit: 'skr',
12
+ containerName: 'Reports',
13
+ environment: 'local',
14
+ runtime: 'node',
15
+ zone: 'local',
16
+ },
17
+ });
18
+ this.ledger = new Ledger(skrType);
19
+ }
20
+ /**
21
+ * Generate Trial Balance
22
+ */
23
+ async getTrialBalance(params) {
24
+ this.logger.log('info', 'Generating trial balance');
25
+ const accounts = await Account.getInstances({
26
+ skrType: this.skrType,
27
+ isActive: true,
28
+ });
29
+ const entries = [];
30
+ let totalDebits = 0;
31
+ let totalCredits = 0;
32
+ for (const account of accounts) {
33
+ // Get balance for the period if specified
34
+ const balance = params?.dateTo
35
+ ? await this.ledger.getAccountBalance(account.accountNumber, params.dateTo)
36
+ : await this.ledger.getAccountBalance(account.accountNumber);
37
+ if (balance.debitTotal !== 0 || balance.creditTotal !== 0) {
38
+ const entry = {
39
+ accountNumber: account.accountNumber,
40
+ accountName: account.accountName,
41
+ debitBalance: balance.debitTotal,
42
+ creditBalance: balance.creditTotal,
43
+ netBalance: balance.balance,
44
+ };
45
+ entries.push(entry);
46
+ totalDebits += balance.debitTotal;
47
+ totalCredits += balance.creditTotal;
48
+ }
49
+ }
50
+ // Sort entries by account number
51
+ entries.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
52
+ const report = {
53
+ date: params?.dateTo || new Date(),
54
+ skrType: this.skrType,
55
+ entries,
56
+ totalDebits,
57
+ totalCredits,
58
+ isBalanced: Math.abs(totalDebits - totalCredits) < 0.01,
59
+ };
60
+ this.logger.log('info', `Trial balance generated with ${entries.length} accounts`);
61
+ return report;
62
+ }
63
+ /**
64
+ * Generate Income Statement (P&L)
65
+ */
66
+ async getIncomeStatement(params) {
67
+ this.logger.log('info', 'Generating income statement');
68
+ // Get revenue accounts
69
+ const revenueAccounts = await Account.getAccountsByType('revenue', this.skrType);
70
+ const expenseAccounts = await Account.getAccountsByType('expense', this.skrType);
71
+ const revenueEntries = [];
72
+ const expenseEntries = [];
73
+ let totalRevenue = 0;
74
+ let totalExpenses = 0;
75
+ // Process revenue accounts
76
+ for (const account of revenueAccounts) {
77
+ const balance = await this.getAccountBalanceForPeriod(account, params);
78
+ if (balance !== 0) {
79
+ const entry = {
80
+ accountNumber: account.accountNumber,
81
+ accountName: account.accountName,
82
+ amount: Math.abs(balance),
83
+ };
84
+ revenueEntries.push(entry);
85
+ totalRevenue += Math.abs(balance);
86
+ }
87
+ }
88
+ // Process expense accounts
89
+ for (const account of expenseAccounts) {
90
+ const balance = await this.getAccountBalanceForPeriod(account, params);
91
+ if (balance !== 0) {
92
+ const entry = {
93
+ accountNumber: account.accountNumber,
94
+ accountName: account.accountName,
95
+ amount: Math.abs(balance),
96
+ };
97
+ expenseEntries.push(entry);
98
+ totalExpenses += Math.abs(balance);
99
+ }
100
+ }
101
+ // Calculate percentages
102
+ revenueEntries.forEach((entry) => {
103
+ entry.percentage =
104
+ totalRevenue > 0 ? (entry.amount / totalRevenue) * 100 : 0;
105
+ });
106
+ expenseEntries.forEach((entry) => {
107
+ entry.percentage =
108
+ totalRevenue > 0 ? (entry.amount / totalRevenue) * 100 : 0;
109
+ });
110
+ // Sort entries by account number
111
+ revenueEntries.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
112
+ expenseEntries.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
113
+ const report = {
114
+ date: params?.dateTo || new Date(),
115
+ skrType: this.skrType,
116
+ revenue: revenueEntries,
117
+ expenses: expenseEntries,
118
+ totalRevenue,
119
+ totalExpenses,
120
+ netIncome: totalRevenue - totalExpenses,
121
+ };
122
+ this.logger.log('info', `Income statement generated: Revenue ${totalRevenue}, Expenses ${totalExpenses}`);
123
+ return report;
124
+ }
125
+ /**
126
+ * Generate Balance Sheet
127
+ */
128
+ async getBalanceSheet(params) {
129
+ this.logger.log('info', 'Generating balance sheet');
130
+ // Get accounts by type
131
+ const assetAccounts = await Account.getAccountsByType('asset', this.skrType);
132
+ const liabilityAccounts = await Account.getAccountsByType('liability', this.skrType);
133
+ const equityAccounts = await Account.getAccountsByType('equity', this.skrType);
134
+ // Process assets
135
+ const currentAssets = [];
136
+ const fixedAssets = [];
137
+ let totalAssets = 0;
138
+ for (const account of assetAccounts) {
139
+ const balance = await this.getAccountBalanceForPeriod(account, params);
140
+ if (balance !== 0) {
141
+ const entry = {
142
+ accountNumber: account.accountNumber,
143
+ accountName: account.accountName,
144
+ amount: Math.abs(balance),
145
+ };
146
+ // Classify as current or fixed based on account class
147
+ if (account.accountClass === 1) {
148
+ currentAssets.push(entry);
149
+ }
150
+ else {
151
+ fixedAssets.push(entry);
152
+ }
153
+ totalAssets += Math.abs(balance);
154
+ }
155
+ }
156
+ // Process liabilities
157
+ const currentLiabilities = [];
158
+ const longTermLiabilities = [];
159
+ let totalLiabilities = 0;
160
+ for (const account of liabilityAccounts) {
161
+ const balance = await this.getAccountBalanceForPeriod(account, params);
162
+ if (balance !== 0) {
163
+ const entry = {
164
+ accountNumber: account.accountNumber,
165
+ accountName: account.accountName,
166
+ amount: Math.abs(balance),
167
+ };
168
+ // Classify as current or long-term based on account number
169
+ if (account.accountNumber.startsWith('16') ||
170
+ account.accountNumber.startsWith('17')) {
171
+ currentLiabilities.push(entry);
172
+ }
173
+ else {
174
+ longTermLiabilities.push(entry);
175
+ }
176
+ totalLiabilities += Math.abs(balance);
177
+ }
178
+ }
179
+ // Process equity
180
+ const equityEntries = [];
181
+ let totalEquity = 0;
182
+ for (const account of equityAccounts) {
183
+ const balance = await this.getAccountBalanceForPeriod(account, params);
184
+ if (balance !== 0) {
185
+ const entry = {
186
+ accountNumber: account.accountNumber,
187
+ accountName: account.accountName,
188
+ amount: Math.abs(balance),
189
+ };
190
+ equityEntries.push(entry);
191
+ totalEquity += Math.abs(balance);
192
+ }
193
+ }
194
+ // Add current year profit/loss
195
+ const incomeStatement = await this.getIncomeStatement(params);
196
+ if (incomeStatement.netIncome !== 0) {
197
+ equityEntries.push({
198
+ accountNumber: '9999',
199
+ accountName: 'Current Year Profit/Loss',
200
+ amount: Math.abs(incomeStatement.netIncome),
201
+ });
202
+ totalEquity += Math.abs(incomeStatement.netIncome);
203
+ }
204
+ // Sort entries
205
+ currentAssets.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
206
+ fixedAssets.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
207
+ currentLiabilities.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
208
+ longTermLiabilities.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
209
+ equityEntries.sort((a, b) => a.accountNumber.localeCompare(b.accountNumber));
210
+ const report = {
211
+ date: params?.dateTo || new Date(),
212
+ skrType: this.skrType,
213
+ assets: {
214
+ current: currentAssets,
215
+ fixed: fixedAssets,
216
+ totalAssets,
217
+ },
218
+ liabilities: {
219
+ current: currentLiabilities,
220
+ longTerm: longTermLiabilities,
221
+ totalLiabilities,
222
+ },
223
+ equity: {
224
+ entries: equityEntries,
225
+ totalEquity,
226
+ },
227
+ isBalanced: Math.abs(totalAssets - (totalLiabilities + totalEquity)) < 0.01,
228
+ };
229
+ this.logger.log('info', `Balance sheet generated: Assets ${totalAssets}, Liabilities ${totalLiabilities}, Equity ${totalEquity}`);
230
+ return report;
231
+ }
232
+ /**
233
+ * Get account balance for a specific period
234
+ */
235
+ async getAccountBalanceForPeriod(account, params) {
236
+ let transactions = await Transaction.getTransactionsByAccount(account.accountNumber, this.skrType);
237
+ // Apply date filter if provided
238
+ if (params?.dateFrom || params?.dateTo) {
239
+ transactions = transactions.filter((transaction) => {
240
+ if (params.dateFrom && transaction.date < params.dateFrom)
241
+ return false;
242
+ if (params.dateTo && transaction.date > params.dateTo)
243
+ return false;
244
+ return true;
245
+ });
246
+ }
247
+ let debitTotal = 0;
248
+ let creditTotal = 0;
249
+ for (const transaction of transactions) {
250
+ if (transaction.debitAccount === account.accountNumber) {
251
+ debitTotal += transaction.amount;
252
+ }
253
+ if (transaction.creditAccount === account.accountNumber) {
254
+ creditTotal += transaction.amount;
255
+ }
256
+ }
257
+ // Calculate net balance based on account type
258
+ switch (account.accountType) {
259
+ case 'asset':
260
+ case 'expense':
261
+ return debitTotal - creditTotal;
262
+ case 'liability':
263
+ case 'equity':
264
+ case 'revenue':
265
+ return creditTotal - debitTotal;
266
+ }
267
+ }
268
+ /**
269
+ * Generate General Ledger report
270
+ */
271
+ async getGeneralLedger(params) {
272
+ this.logger.log('info', 'Generating general ledger');
273
+ const accounts = await Account.getInstances({
274
+ skrType: this.skrType,
275
+ isActive: true,
276
+ });
277
+ const ledgerEntries = [];
278
+ for (const account of accounts) {
279
+ const transactions = await this.getAccountTransactions(account.accountNumber, params);
280
+ if (transactions.length > 0) {
281
+ let runningBalance = 0;
282
+ const accountEntries = [];
283
+ for (const transaction of transactions) {
284
+ const isDebit = transaction.debitAccount === account.accountNumber;
285
+ const amount = transaction.amount;
286
+ // Update running balance based on account type
287
+ if (account.accountType === 'asset' ||
288
+ account.accountType === 'expense') {
289
+ runningBalance += isDebit ? amount : -amount;
290
+ }
291
+ else {
292
+ runningBalance += isDebit ? -amount : amount;
293
+ }
294
+ accountEntries.push({
295
+ date: transaction.date,
296
+ reference: transaction.reference,
297
+ description: transaction.description,
298
+ debit: isDebit ? amount : 0,
299
+ credit: !isDebit ? amount : 0,
300
+ balance: runningBalance,
301
+ });
302
+ }
303
+ ledgerEntries.push({
304
+ accountNumber: account.accountNumber,
305
+ accountName: account.accountName,
306
+ accountType: account.accountType,
307
+ entries: accountEntries,
308
+ finalBalance: runningBalance,
309
+ });
310
+ }
311
+ }
312
+ return {
313
+ date: params?.dateTo || new Date(),
314
+ skrType: this.skrType,
315
+ accounts: ledgerEntries,
316
+ };
317
+ }
318
+ /**
319
+ * Get account transactions for reporting
320
+ */
321
+ async getAccountTransactions(accountNumber, params) {
322
+ let transactions = await Transaction.getTransactionsByAccount(accountNumber, this.skrType);
323
+ // Apply date filter
324
+ if (params?.dateFrom || params?.dateTo) {
325
+ transactions = transactions.filter((transaction) => {
326
+ if (params.dateFrom && transaction.date < params.dateFrom)
327
+ return false;
328
+ if (params.dateTo && transaction.date > params.dateTo)
329
+ return false;
330
+ return true;
331
+ });
332
+ }
333
+ // Sort by date
334
+ transactions.sort((a, b) => a.date.getTime() - b.date.getTime());
335
+ return transactions;
336
+ }
337
+ /**
338
+ * Generate Cash Flow Statement
339
+ */
340
+ async getCashFlowStatement(params) {
341
+ this.logger.log('info', 'Generating cash flow statement');
342
+ // Get cash and bank accounts
343
+ const cashAccounts = ['1000', '1100', '1200', '1210']; // Standard cash/bank accounts
344
+ let operatingCashFlow = 0;
345
+ let investingCashFlow = 0;
346
+ let financingCashFlow = 0;
347
+ for (const accountNumber of cashAccounts) {
348
+ const account = await Account.getAccountByNumber(accountNumber, this.skrType);
349
+ if (!account)
350
+ continue;
351
+ const transactions = await this.getAccountTransactions(accountNumber, params);
352
+ for (const transaction of transactions) {
353
+ const otherAccount = transaction.debitAccount === accountNumber
354
+ ? transaction.creditAccount
355
+ : transaction.debitAccount;
356
+ const otherAccountObj = await Account.getAccountByNumber(otherAccount, this.skrType);
357
+ if (!otherAccountObj)
358
+ continue;
359
+ const amount = transaction.debitAccount === accountNumber
360
+ ? transaction.amount
361
+ : -transaction.amount;
362
+ // Classify cash flow
363
+ if (otherAccountObj.accountType === 'revenue' ||
364
+ otherAccountObj.accountType === 'expense') {
365
+ operatingCashFlow += amount;
366
+ }
367
+ else if (otherAccountObj.accountClass === 0) {
368
+ // Fixed assets
369
+ investingCashFlow += amount;
370
+ }
371
+ else if (otherAccountObj.accountType === 'liability' ||
372
+ otherAccountObj.accountType === 'equity') {
373
+ financingCashFlow += amount;
374
+ }
375
+ }
376
+ }
377
+ return {
378
+ date: params?.dateTo || new Date(),
379
+ skrType: this.skrType,
380
+ operatingActivities: operatingCashFlow,
381
+ investingActivities: investingCashFlow,
382
+ financingActivities: financingCashFlow,
383
+ netCashFlow: operatingCashFlow + investingCashFlow + financingCashFlow,
384
+ };
385
+ }
386
+ /**
387
+ * Export report to CSV format
388
+ */
389
+ async exportToCSV(reportType, params) {
390
+ let csvContent = '';
391
+ switch (reportType) {
392
+ case 'trial_balance':
393
+ const trialBalance = await this.getTrialBalance(params);
394
+ csvContent = this.trialBalanceToCSV(trialBalance);
395
+ break;
396
+ case 'income_statement':
397
+ const incomeStatement = await this.getIncomeStatement(params);
398
+ csvContent = this.incomeStatementToCSV(incomeStatement);
399
+ break;
400
+ case 'balance_sheet':
401
+ const balanceSheet = await this.getBalanceSheet(params);
402
+ csvContent = this.balanceSheetToCSV(balanceSheet);
403
+ break;
404
+ }
405
+ return csvContent;
406
+ }
407
+ /**
408
+ * Convert trial balance to CSV
409
+ */
410
+ trialBalanceToCSV(report) {
411
+ const lines = [];
412
+ lines.push('"Account Number";"Account Name";"Debit";"Credit";"Balance"');
413
+ for (const entry of report.entries) {
414
+ lines.push(`"${entry.accountNumber}";"${entry.accountName}";${entry.debitBalance};${entry.creditBalance};${entry.netBalance}`);
415
+ }
416
+ lines.push(`"TOTAL";"";"${report.totalDebits}";"${report.totalCredits}";"""`);
417
+ return lines.join('\n');
418
+ }
419
+ /**
420
+ * Convert income statement to CSV
421
+ */
422
+ incomeStatementToCSV(report) {
423
+ const lines = [];
424
+ lines.push('"Type";"Account Number";"Account Name";"Amount";"Percentage"');
425
+ lines.push('"REVENUE";"";"";"";""');
426
+ for (const entry of report.revenue) {
427
+ lines.push(`"Revenue";"${entry.accountNumber}";"${entry.accountName}";${entry.amount};${entry.percentage?.toFixed(2)}%`);
428
+ }
429
+ lines.push(`"Total Revenue";"";"";"${report.totalRevenue}";"""`);
430
+ lines.push('"";"";"";"";""');
431
+ lines.push('"EXPENSES";"";"";"";""');
432
+ for (const entry of report.expenses) {
433
+ lines.push(`"Expense";"${entry.accountNumber}";"${entry.accountName}";${entry.amount};${entry.percentage?.toFixed(2)}%`);
434
+ }
435
+ lines.push(`"Total Expenses";"";"";"${report.totalExpenses}";"""`);
436
+ lines.push('"";"";"";"";""');
437
+ lines.push(`"NET INCOME";"";"";"${report.netIncome}";"""`);
438
+ return lines.join('\n');
439
+ }
440
+ /**
441
+ * Convert balance sheet to CSV
442
+ */
443
+ balanceSheetToCSV(report) {
444
+ const lines = [];
445
+ lines.push('"Category";"Account Number";"Account Name";"Amount"');
446
+ lines.push('"ASSETS";"";"";"";');
447
+ lines.push('"Current Assets";"";"";"";');
448
+ for (const entry of report.assets.current) {
449
+ lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
450
+ }
451
+ lines.push('"Fixed Assets";"";"";"";');
452
+ for (const entry of report.assets.fixed) {
453
+ lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
454
+ }
455
+ lines.push(`"Total Assets";"";"";"${report.assets.totalAssets}"`);
456
+ lines.push('"";"";"";"";');
457
+ lines.push('"LIABILITIES";"";"";"";');
458
+ lines.push('"Current Liabilities";"";"";"";');
459
+ for (const entry of report.liabilities.current) {
460
+ lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
461
+ }
462
+ lines.push('"Long-term Liabilities";"";"";"";');
463
+ for (const entry of report.liabilities.longTerm) {
464
+ lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
465
+ }
466
+ lines.push(`"Total Liabilities";"";"";"${report.liabilities.totalLiabilities}"`);
467
+ lines.push('"";"";"";"";');
468
+ lines.push('"EQUITY";"";"";"";');
469
+ for (const entry of report.equity.entries) {
470
+ lines.push(`"";"${entry.accountNumber}";"${entry.accountName}";${entry.amount}`);
471
+ }
472
+ lines.push(`"Total Equity";"";"";"${report.equity.totalEquity}"`);
473
+ lines.push('"";"";"";"";');
474
+ lines.push(`"Total Liabilities + Equity";"";"";"${report.liabilities.totalLiabilities + report.equity.totalEquity}"`);
475
+ return lines.join('\n');
476
+ }
477
+ /**
478
+ * Export to DATEV format
479
+ */
480
+ async exportToDATEV(params) {
481
+ // DATEV format is specific to German accounting software
482
+ // This is a simplified implementation
483
+ const transactions = await Transaction.getInstances({
484
+ skrType: this.skrType,
485
+ status: 'posted',
486
+ });
487
+ const lines = [];
488
+ // DATEV header
489
+ lines.push('EXTF;510;21;"Buchungsstapel";1;;;;;;;;;;;;;;');
490
+ for (const transaction of transactions) {
491
+ const date = transaction.date
492
+ .toISOString()
493
+ .split('T')[0]
494
+ .replace(/-/g, '');
495
+ const line = [
496
+ transaction.amount.toFixed(2).replace('.', ','),
497
+ 'S',
498
+ 'EUR',
499
+ '',
500
+ '',
501
+ transaction.debitAccount,
502
+ transaction.creditAccount,
503
+ '',
504
+ date,
505
+ '',
506
+ transaction.description.substring(0, 60),
507
+ '',
508
+ ].join(';');
509
+ lines.push(line);
510
+ }
511
+ return lines.join('\n');
512
+ }
513
+ }
514
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmNsYXNzZXMucmVwb3J0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3Nrci5jbGFzc2VzLnJlcG9ydHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFZakQsTUFBTSxPQUFPLE9BQU87SUFJbEIsWUFBb0IsT0FBaUI7UUFBakIsWUFBTyxHQUFQLE9BQU8sQ0FBVTtRQUNuQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7WUFDMUMsVUFBVSxFQUFFO2dCQUNWLE9BQU8sRUFBRSxRQUFRO2dCQUNqQixXQUFXLEVBQUUsS0FBSztnQkFDbEIsYUFBYSxFQUFFLFNBQVM7Z0JBQ3hCLFdBQVcsRUFBRSxPQUFPO2dCQUNwQixPQUFPLEVBQUUsTUFBTTtnQkFDZixJQUFJLEVBQUUsT0FBTzthQUNkO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsZUFBZSxDQUMxQixNQUFzQjtRQUV0QixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsMEJBQTBCLENBQUMsQ0FBQztRQUVwRCxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFDMUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1lBQ3JCLFFBQVEsRUFBRSxJQUFJO1NBQ2YsQ0FBQyxDQUFDO1FBRUgsTUFBTSxPQUFPLEdBQXlCLEVBQUUsQ0FBQztR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
@@ -0,0 +1,37 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { TSKRType, TTransactionStatus, ITransactionData } from './skr.types.js';
3
+ declare const SmartDataDbDoc: typeof plugins.smartdata.SmartDataDbDoc;
4
+ export declare class Transaction extends SmartDataDbDoc<Transaction, Transaction> {
5
+ id: string;
6
+ transactionNumber: string;
7
+ date: Date;
8
+ debitAccount: string;
9
+ creditAccount: string;
10
+ amount: number;
11
+ description: string;
12
+ reference: string;
13
+ skrType: TSKRType;
14
+ vatAmount: number;
15
+ costCenter: string;
16
+ status: TTransactionStatus;
17
+ reversalOf: string;
18
+ reversedBy: string;
19
+ period: string;
20
+ fiscalYear: number;
21
+ createdAt: Date;
22
+ postedAt: Date;
23
+ createdBy: string;
24
+ constructor(data?: Partial<ITransactionData>);
25
+ private generateTransactionNumber;
26
+ static createTransaction(data: ITransactionData): Promise<Transaction>;
27
+ static getTransactionById(id: string): Promise<Transaction | null>;
28
+ static getTransactionsByAccount(accountNumber: string, skrType: TSKRType): Promise<Transaction[]>;
29
+ static getTransactionsByPeriod(period: string, skrType: TSKRType): Promise<Transaction[]>;
30
+ static getTransactionsByDateRange(dateFrom: Date, dateTo: Date, skrType: TSKRType): Promise<Transaction[]>;
31
+ validateAndPost(): Promise<void>;
32
+ private validateTransaction;
33
+ private updateAccountBalances;
34
+ reverseTransaction(): Promise<Transaction>;
35
+ beforeSave(): Promise<void>;
36
+ }
37
+ export {};