@fin.cx/skr 1.0.0 → 1.2.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 (54) hide show
  1. package/dist_ts/index.d.ts +6 -0
  2. package/dist_ts/index.js +7 -1
  3. package/dist_ts/plugins.d.ts +8 -1
  4. package/dist_ts/plugins.js +10 -2
  5. package/dist_ts/skr.api.d.ts +70 -0
  6. package/dist_ts/skr.api.js +354 -3
  7. package/dist_ts/skr.classes.journalentry.d.ts +1 -0
  8. package/dist_ts/skr.classes.journalentry.js +55 -15
  9. package/dist_ts/skr.classes.ledger.d.ts +4 -0
  10. package/dist_ts/skr.classes.ledger.js +72 -1
  11. package/dist_ts/skr.classes.reports.js +56 -22
  12. package/dist_ts/skr.export.accounts.d.ts +53 -0
  13. package/dist_ts/skr.export.accounts.js +111 -0
  14. package/dist_ts/skr.export.balances.d.ts +59 -0
  15. package/dist_ts/skr.export.balances.js +205 -0
  16. package/dist_ts/skr.export.d.ts +110 -0
  17. package/dist_ts/skr.export.js +315 -0
  18. package/dist_ts/skr.export.ledger.d.ts +95 -0
  19. package/dist_ts/skr.export.ledger.js +164 -0
  20. package/dist_ts/skr.export.pdf.d.ts +82 -0
  21. package/dist_ts/skr.export.pdf.js +548 -0
  22. package/dist_ts/skr.invoice.adapter.d.ts +98 -0
  23. package/dist_ts/skr.invoice.adapter.js +476 -0
  24. package/dist_ts/skr.invoice.booking.d.ts +102 -0
  25. package/dist_ts/skr.invoice.booking.js +556 -0
  26. package/dist_ts/skr.invoice.entity.d.ts +287 -0
  27. package/dist_ts/skr.invoice.entity.js +2 -0
  28. package/dist_ts/skr.invoice.mapper.d.ts +69 -0
  29. package/dist_ts/skr.invoice.mapper.js +401 -0
  30. package/dist_ts/skr.invoice.storage.d.ts +140 -0
  31. package/dist_ts/skr.invoice.storage.js +529 -0
  32. package/dist_ts/skr.security.d.ts +65 -0
  33. package/dist_ts/skr.security.js +319 -0
  34. package/dist_ts/skr.types.d.ts +1 -0
  35. package/package.json +18 -12
  36. package/readme.md +461 -132
  37. package/ts/index.ts +6 -0
  38. package/ts/plugins.ts +22 -1
  39. package/ts/skr.api.ts +489 -2
  40. package/ts/skr.classes.journalentry.ts +63 -14
  41. package/ts/skr.classes.ledger.ts +85 -0
  42. package/ts/skr.classes.reports.ts +64 -21
  43. package/ts/skr.export.accounts.ts +154 -0
  44. package/ts/skr.export.balances.ts +270 -0
  45. package/ts/skr.export.ledger.ts +249 -0
  46. package/ts/skr.export.pdf.ts +601 -0
  47. package/ts/skr.export.ts +443 -0
  48. package/ts/skr.invoice.adapter.ts +581 -0
  49. package/ts/skr.invoice.booking.ts +738 -0
  50. package/ts/skr.invoice.entity.ts +351 -0
  51. package/ts/skr.invoice.mapper.ts +486 -0
  52. package/ts/skr.invoice.storage.ts +710 -0
  53. package/ts/skr.security.ts +405 -0
  54. package/ts/skr.types.ts +1 -0
@@ -0,0 +1,249 @@
1
+ import * as plugins from './plugins.js';
2
+ import * as path from 'path';
3
+ import type { ITransactionData, IJournalEntry, IJournalEntryLine } from './skr.types.js';
4
+ import { createWriteStream, type WriteStream } from 'fs';
5
+
6
+ // Extended interfaces for export with additional tracking fields
7
+ export interface ITransactionDataExport extends ITransactionData {
8
+ _id?: string;
9
+ postingDate?: Date;
10
+ currency?: string;
11
+ createdAt?: Date | string;
12
+ modifiedAt?: Date | string;
13
+ reversalOf?: string;
14
+ reversedBy?: string;
15
+ taxCode?: string;
16
+ project?: string;
17
+ vatAccount?: string;
18
+ }
19
+
20
+ export interface IJournalEntryExport extends IJournalEntry {
21
+ _id?: string;
22
+ postingDate?: Date;
23
+ currency?: string;
24
+ journal?: string;
25
+ createdAt?: Date | string;
26
+ modifiedAt?: Date | string;
27
+ reversalOf?: string;
28
+ reversedBy?: string;
29
+ }
30
+
31
+ export interface IJournalEntryLineExport extends IJournalEntryLine {
32
+ taxCode?: string;
33
+ project?: string;
34
+ }
35
+
36
+ export interface ILedgerEntry {
37
+ schema_version: string;
38
+ entry_id: string;
39
+ booking_date: string;
40
+ posting_date: string;
41
+ period?: string;
42
+ currency: string;
43
+ journal: string;
44
+ description: string;
45
+ reference?: string;
46
+ lines: ILedgerLine[];
47
+ document_refs?: IDocumentRef[];
48
+ created_at: string;
49
+ modified_at?: string;
50
+ user?: string;
51
+ reversal_of?: string;
52
+ reversed_by?: string;
53
+ }
54
+
55
+ export interface ILedgerLine {
56
+ posting_id: string;
57
+ account_code: string;
58
+ debit: string;
59
+ credit: string;
60
+ tax_code?: string;
61
+ cost_center?: string;
62
+ project?: string;
63
+ description?: string;
64
+ }
65
+
66
+ export interface IDocumentRef {
67
+ content_hash: string;
68
+ doc_role: 'invoice' | 'receipt' | 'contract' | 'bank-statement' | 'other';
69
+ doc_mime: string;
70
+ doc_original_name?: string;
71
+ }
72
+
73
+ export class LedgerExporter {
74
+ private exportPath: string;
75
+ private stream: WriteStream | null = null;
76
+ private entryCount: number = 0;
77
+
78
+ constructor(exportPath: string) {
79
+ this.exportPath = exportPath;
80
+ }
81
+
82
+ /**
83
+ * Initializes the NDJSON export stream
84
+ */
85
+ public async initialize(): Promise<void> {
86
+ const ledgerPath = path.join(this.exportPath, 'data', 'accounting', 'ledger.ndjson');
87
+ await plugins.smartfile.fs.ensureDir(path.dirname(ledgerPath));
88
+
89
+ this.stream = createWriteStream(ledgerPath, {
90
+ encoding: 'utf8',
91
+ flags: 'w'
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Exports a transaction as a ledger entry
97
+ */
98
+ public async exportTransaction(transaction: ITransactionDataExport): Promise<void> {
99
+ if (!this.stream) {
100
+ throw new Error('Ledger exporter not initialized');
101
+ }
102
+
103
+ const entry: ILedgerEntry = {
104
+ schema_version: '1.0',
105
+ entry_id: transaction._id || plugins.smartunique.shortId(),
106
+ booking_date: this.formatDate(transaction.date),
107
+ posting_date: this.formatDate(transaction.postingDate || transaction.date),
108
+ currency: transaction.currency || 'EUR',
109
+ journal: 'GL',
110
+ description: transaction.description,
111
+ reference: transaction.reference,
112
+ lines: [],
113
+ created_at: transaction.createdAt ? new Date(transaction.createdAt).toISOString() : new Date().toISOString(),
114
+ modified_at: transaction.modifiedAt ? new Date(transaction.modifiedAt).toISOString() : undefined,
115
+ reversal_of: transaction.reversalOf,
116
+ reversed_by: transaction.reversedBy
117
+ };
118
+
119
+ // Add debit line
120
+ if (transaction.amount > 0) {
121
+ entry.lines.push({
122
+ posting_id: `${entry.entry_id}-1`,
123
+ account_code: transaction.debitAccount,
124
+ debit: transaction.amount.toFixed(2),
125
+ credit: '0.00',
126
+ tax_code: transaction.taxCode,
127
+ cost_center: transaction.costCenter,
128
+ project: transaction.project
129
+ });
130
+
131
+ // Add credit line
132
+ entry.lines.push({
133
+ posting_id: `${entry.entry_id}-2`,
134
+ account_code: transaction.creditAccount,
135
+ debit: '0.00',
136
+ credit: transaction.amount.toFixed(2)
137
+ });
138
+ }
139
+
140
+ // Add VAT lines if applicable
141
+ if (transaction.vatAmount && transaction.vatAmount > 0) {
142
+ entry.lines.push({
143
+ posting_id: `${entry.entry_id}-3`,
144
+ account_code: transaction.vatAccount || '1576', // Default VAT account
145
+ debit: transaction.vatAmount.toFixed(2),
146
+ credit: '0.00',
147
+ description: 'Vorsteuer'
148
+ });
149
+ }
150
+
151
+ await this.writeLine(entry);
152
+ }
153
+
154
+ /**
155
+ * Exports a journal entry
156
+ */
157
+ public async exportJournalEntry(journalEntry: IJournalEntryExport): Promise<void> {
158
+ if (!this.stream) {
159
+ throw new Error('Ledger exporter not initialized');
160
+ }
161
+
162
+ const entry: ILedgerEntry = {
163
+ schema_version: '1.0',
164
+ entry_id: journalEntry._id || plugins.smartunique.shortId(),
165
+ booking_date: this.formatDate(journalEntry.date),
166
+ posting_date: this.formatDate(journalEntry.postingDate || journalEntry.date),
167
+ currency: journalEntry.currency || 'EUR',
168
+ journal: journalEntry.journal || 'GL',
169
+ description: journalEntry.description,
170
+ reference: journalEntry.reference,
171
+ lines: [],
172
+ created_at: journalEntry.createdAt ? new Date(journalEntry.createdAt).toISOString() : new Date().toISOString(),
173
+ modified_at: journalEntry.modifiedAt ? new Date(journalEntry.modifiedAt).toISOString() : undefined,
174
+ reversal_of: journalEntry.reversalOf,
175
+ reversed_by: journalEntry.reversedBy
176
+ };
177
+
178
+ // Convert journal entry lines
179
+ journalEntry.lines.forEach((line, index) => {
180
+ const extLine = line as IJournalEntryLineExport;
181
+ entry.lines.push({
182
+ posting_id: `${entry.entry_id}-${index + 1}`,
183
+ account_code: line.accountNumber,
184
+ debit: (line.debit || 0).toFixed(2),
185
+ credit: (line.credit || 0).toFixed(2),
186
+ tax_code: extLine.taxCode,
187
+ cost_center: line.costCenter,
188
+ project: extLine.project,
189
+ description: line.description
190
+ });
191
+ });
192
+
193
+ await this.writeLine(entry);
194
+ }
195
+
196
+ /**
197
+ * Writes a single NDJSON line
198
+ */
199
+ private async writeLine(entry: ILedgerEntry): Promise<void> {
200
+ return new Promise((resolve, reject) => {
201
+ if (!this.stream) {
202
+ reject(new Error('Stream not initialized'));
203
+ return;
204
+ }
205
+
206
+ const line = JSON.stringify(entry) + '\n';
207
+ this.stream.write(line, (error) => {
208
+ if (error) {
209
+ reject(error);
210
+ } else {
211
+ this.entryCount++;
212
+ resolve();
213
+ }
214
+ });
215
+ });
216
+ }
217
+
218
+ /**
219
+ * Formats a date to ISO date string
220
+ */
221
+ private formatDate(date: Date | string): string {
222
+ if (typeof date === 'string') {
223
+ return date.split('T')[0];
224
+ }
225
+ return date.toISOString().split('T')[0];
226
+ }
227
+
228
+ /**
229
+ * Closes the export stream
230
+ */
231
+ public async close(): Promise<number> {
232
+ return new Promise((resolve) => {
233
+ if (this.stream) {
234
+ this.stream.end(() => {
235
+ resolve(this.entryCount);
236
+ });
237
+ } else {
238
+ resolve(this.entryCount);
239
+ }
240
+ });
241
+ }
242
+
243
+ /**
244
+ * Gets the number of exported entries
245
+ */
246
+ public getEntryCount(): number {
247
+ return this.entryCount;
248
+ }
249
+ }