@fin.cx/compatibility 4.1.0 → 5.0.1
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/00_commitinfo_data.js +1 -1
- package/dist_ts/error.d.ts +7 -3
- package/dist_ts/error.js +1 -1
- package/dist_ts/extf/index.d.ts +42 -9
- package/dist_ts/extf/index.js +146 -11
- package/package.json +3 -3
- package/readme.md +7 -4
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/error.ts +7 -3
- package/ts/extf/index.ts +168 -14
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@fin.cx/compatibility',
|
|
6
|
-
version: '
|
|
6
|
+
version: '5.0.1',
|
|
7
7
|
description: 'Exchange formats of third-party accounting systems: the EXTF Buchungsstapel in Windows-1252 on the rows of @fin.cx/skr, and the document-image archive (document.xml and ZIP)'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLCtLQUErSztDQUM3TCxDQUFBIn0=
|
package/dist_ts/error.d.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Why an exchange file could not be written:
|
|
3
|
-
* - `invalid_bookings`: a draft the account policy refuses, the message names it;
|
|
4
|
-
* bookings handed over to a correction Buchungsstapel (a correction file passed as the state handed over);
|
|
3
|
+
* - `invalid_bookings`: a draft the account policy refuses, the message names it; a general reversal among the
|
|
4
|
+
* bookings handed over to a correction Buchungsstapel (a correction file passed as the state handed over); or a row
|
|
5
|
+
* or booking a Buchungsstapel does not hold (no day, an amount that is not positive) or whose Belegdatum lies
|
|
6
|
+
* outside the period of the header, named;
|
|
7
|
+
* - `invalid_header`: a header whose period ends before it begins or does not lie within the one Wirtschaftsjahr
|
|
8
|
+
* beginning on its Wirtschaftsjahr-Beginn;
|
|
5
9
|
* - `export_failed`: the conversion into rows failed;
|
|
6
10
|
* - `invalid_documents`: a document of a document-image archive DATEV does not take (its GUID, its format), or none;
|
|
7
11
|
* - `nothing_to_correct`: a correction Buchungsstapel whose current bookings are the ones handed over;
|
|
8
12
|
* - `handed_over_cost_centres_unknown`: a correction of a period whose bookings handed over include one whose cost
|
|
9
13
|
* centres its record does not state (stored before 4.1) and no rows sent were given; the message names it.
|
|
10
14
|
*/
|
|
11
|
-
export type TCompatibilityErrorCode = 'invalid_bookings' | 'export_failed' | 'invalid_documents' | 'nothing_to_correct' | 'handed_over_cost_centres_unknown';
|
|
15
|
+
export type TCompatibilityErrorCode = 'invalid_bookings' | 'invalid_header' | 'export_failed' | 'invalid_documents' | 'nothing_to_correct' | 'handed_over_cost_centres_unknown';
|
|
12
16
|
export declare class CompatibilityError extends Error {
|
|
13
17
|
readonly code: TCompatibilityErrorCode;
|
|
14
18
|
constructor(codeArg: TCompatibilityErrorCode, messageArg: string);
|
package/dist_ts/error.js
CHANGED
|
@@ -5,4 +5,4 @@ export class CompatibilityError extends Error {
|
|
|
5
5
|
this.code = codeArg;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9lcnJvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFnQkEsTUFBTSxPQUFPLGtCQUFtQixTQUFRLEtBQUs7SUFHM0MsWUFBWSxPQUFnQyxFQUFFLFVBQWtCO1FBQzlELEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNsQixJQUFJLENBQUMsSUFBSSxHQUFHLG9CQUFvQixDQUFDO1FBQ2pDLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDO0lBQ3RCLENBQUM7Q0FDRiJ9
|
package/dist_ts/extf/index.d.ts
CHANGED
|
@@ -41,9 +41,12 @@ export declare const bookingsOfRows: (rowsArg: readonly IDatevBuchungsstapelRow[
|
|
|
41
41
|
* How many rows two Buchungsstapel of one period do not share, compared on
|
|
42
42
|
* what a booking says (its day, amount, side, accounts, BU key, Belegfeld 1,
|
|
43
43
|
* cost centres, and whether it is a general reversal) and not on its wording or its document link. The rows are
|
|
44
|
-
* compared as a multiset: a row that stands twice in one and once in the other differs once.
|
|
45
|
-
*
|
|
46
|
-
*
|
|
44
|
+
* compared as a multiset: a row that stands twice in one and once in the other differs once. Both sides are compared
|
|
45
|
+
* as a file states them (`comparableOf`: a `"` in a text field as `'`, Belegfeld 1 as skr's writer writes it, a
|
|
46
|
+
* character Windows-1252 cannot hold as `?`), so bookings stored of rows before writing and bookings read from a
|
|
47
|
+
* file compare alike. A booking stored before 4.1, which does not record its cost centres, never differs on them (`pairBookings`); compare
|
|
48
|
+
* `bookingsOfRows` of the rows sent for an answer that counts them. A booking a Buchungsstapel cannot hold (no day,
|
|
49
|
+
* no positive amount) is refused (`invalid_bookings`).
|
|
47
50
|
*/
|
|
48
51
|
export declare const differingBookingCount: (leftArg: readonly IExportBooking[], rightArg: readonly IExportBooking[]) => number;
|
|
49
52
|
/**
|
|
@@ -96,11 +99,37 @@ export interface IBuchungsstapelFile {
|
|
|
96
99
|
csv: string;
|
|
97
100
|
/** the file in Windows-1252, as it is handed over */
|
|
98
101
|
bytes: Uint8Array;
|
|
102
|
+
/** the rows as they were given to the writer; the file states them as `rowsAsWritten` does */
|
|
99
103
|
rows: IDatevBuchungsstapelRow[];
|
|
104
|
+
/**
|
|
105
|
+
* The bookings the file states, read back from its bytes (`@fin.cx/skr` `readExtfBuchungsstapel`): a `"` in a
|
|
106
|
+
* text field as `'`, Belegfeld 1 as skr's writer writes it (cut to 36 characters before skr 7.3.0; since then a value
|
|
107
|
+
* DATEV does not take mapped, `datevBelegfeldOf`), a character Windows-1252 cannot hold as `?`. What a file
|
|
108
|
+
* read back is compared with, and what a correction's `handedOver` is (4.1 and before: the rows' bookings before
|
|
109
|
+
* writing).
|
|
110
|
+
*/
|
|
100
111
|
bookings: IExportBooking[];
|
|
101
112
|
/** the characters Windows-1252 cannot write, each written as `?`, with the row and field it stands in */
|
|
102
113
|
replacedCharacters: IBuchungsstapelReplacement[];
|
|
103
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Rows as a Buchungsstapel file states them: each row written by the writer (`@fin.cx/skr` `writeExtfBuchungsstapel`,
|
|
117
|
+
* which writes a `"` in a text field as `'` and cuts a field to its DATEV length), encoded in Windows-1252 (a
|
|
118
|
+
* character it cannot hold written `?`, `encodeWindows1252`), and read back (`@fin.cx/skr` `readExtfBuchungsstapel`),
|
|
119
|
+
* in the order given. Every rule of the writer, the encoding and the reader applies because the rows go through them,
|
|
120
|
+
* not through a copy of their rules. The rows of each calendar year are written as one file whose header spans their
|
|
121
|
+
* days; the header states nothing a row is read by beyond its days. A row the writer or the reader refuses throws as
|
|
122
|
+
* it does.
|
|
123
|
+
*/
|
|
124
|
+
export declare const rowsAsWritten: (rowsArg: readonly IDatevBuchungsstapelRow[]) => IDatevBuchungsstapelRow[];
|
|
125
|
+
/**
|
|
126
|
+
* The bookings of rows as a Buchungsstapel file states them (`rowsAsWritten`): what a file handed over, read back
|
|
127
|
+
* with `readExtfBuchungsstapel`, is compared with. `bookingsOfRows` of the rows before writing keeps what the file
|
|
128
|
+
* does not (a Belegfeld 1 the writer changes: cut to 36 characters before skr 7.3.0, mapped since where DATEV does
|
|
129
|
+
* not take it; a character Windows-1252 cannot hold), and Belegfeld 1 is compared, so such a booking would differ
|
|
130
|
+
* from the file forever.
|
|
131
|
+
*/
|
|
132
|
+
export declare const bookingsAsWritten: (rowsArg: readonly IDatevBuchungsstapelRow[]) => IExportBooking[];
|
|
104
133
|
/** Writes a Buchungsstapel: the rows of the drafts, the header and the caption row, encoded in Windows-1252. */
|
|
105
134
|
export declare const writeBuchungsstapel: (optionsArg: IBuchungsstapelOptions) => IBuchungsstapelFile;
|
|
106
135
|
/**
|
|
@@ -113,8 +142,10 @@ export declare const rowOfBooking: (bookingArg: IExportBooking) => IDatevBuchung
|
|
|
113
142
|
* handed over that the current ones no longer hold (`reversed`, each once for each time it is missing), the ones they
|
|
114
143
|
* still hold (`kept`, as they were handed over) and the current rows the bookings handed over do not hold (`added`),
|
|
115
144
|
* each in its order. A booking that stands in both is kept: a changed text or document link is no changed booking,
|
|
116
|
-
* a changed cost centre is.
|
|
117
|
-
*
|
|
145
|
+
* a changed cost centre is. The current rows are compared as a file states them (`bookingsAsWritten`), as the
|
|
146
|
+
* bookings handed over are; `added` are the rows themselves, which the writer writes. A booking handed over whose
|
|
147
|
+
* cost centres its record does not state (stored before 4.1) is refused (`handed_over_cost_centres_unknown`): pass
|
|
148
|
+
* `bookingsOfRows` of the rows sent instead.
|
|
118
149
|
*/
|
|
119
150
|
export declare const correctionOf: (handedOverArg: readonly IExportBooking[], currentArg: readonly IDatevBuchungsstapelRow[]) => {
|
|
120
151
|
reversed: IExportBooking[];
|
|
@@ -131,14 +162,16 @@ export interface ICorrectionBuchungsstapelOptions {
|
|
|
131
162
|
* The bookings of the period as they were handed over, as a whole: the bookings of its Buchungsstapel as stored
|
|
132
163
|
* (`IBuchungsstapelFile.bookings`), or after a correction the period's bookings as that correction left them
|
|
133
164
|
* (`bookingsAfter`). Each must state its cost centres: one stored before 4.1 does not, and is refused
|
|
134
|
-
* (`handed_over_cost_centres_unknown`); pass the rows sent for it.
|
|
165
|
+
* (`handed_over_cost_centres_unknown`); pass the rows sent for it. Bookings stored by any version, before or after
|
|
166
|
+
* writing, are compared as a file states them (`comparableOf`), so a reference the writer changed is no change.
|
|
135
167
|
*/
|
|
136
168
|
handedOver?: readonly IExportBooking[];
|
|
137
169
|
/**
|
|
138
170
|
* The rows of the Buchungsstapel as it was sent: the transmitted file read back (`@fin.cx/skr`
|
|
139
|
-
* `readExtfBuchungsstapel(bytes).rows`, skr
|
|
140
|
-
*
|
|
141
|
-
* bookings were stored
|
|
171
|
+
* `readExtfBuchungsstapel(bytes).rows`, skr 7.0.1 and later) or the rows given to the writer
|
|
172
|
+
* (`IBuchungsstapelFile.rows`), taken as the file states them (`bookingsAsWritten`). What DATEV received, cost
|
|
173
|
+
* centres (fields 37 and 38) included, so a reversal mirrors it exactly. For a Stapel whose bookings were stored
|
|
174
|
+
* before 4.1, which record no cost centres.
|
|
142
175
|
*/
|
|
143
176
|
handedOverRows?: readonly IDatevBuchungsstapelRow[];
|
|
144
177
|
/** the period's drafts as they stand now */
|
package/dist_ts/extf/index.js
CHANGED
|
@@ -97,16 +97,32 @@ const pairBookings = (leftArg, rightArg) => {
|
|
|
97
97
|
pairLeft(false);
|
|
98
98
|
return { leftPaired, rightPaired };
|
|
99
99
|
};
|
|
100
|
+
/**
|
|
101
|
+
* Bookings as a Buchungsstapel file states them, for comparing: each written as the row it was written as
|
|
102
|
+
* (`rowOfBooking`) and read back (`bookingsAsWritten`), so bookings stored of rows before writing (4.1 and before)
|
|
103
|
+
* and bookings read from a file compare alike. One that records no cost centres (stored before 4.1) keeps recording
|
|
104
|
+
* none, so it still never differs on them. A booking a Buchungsstapel cannot hold is refused (`invalid_bookings`).
|
|
105
|
+
*/
|
|
106
|
+
const comparableOf = (bookingsArg) => bookingsAsWritten(bookingsArg.map((bookingArg) => rowOfBooking(bookingArg))).map((bookingArg, indexArg) => {
|
|
107
|
+
if (recordsCostCentres(bookingsArg[indexArg])) {
|
|
108
|
+
return bookingArg;
|
|
109
|
+
}
|
|
110
|
+
const { kost1: _kost1, kost2: _kost2, ...unrecorded } = bookingArg;
|
|
111
|
+
return unrecorded;
|
|
112
|
+
});
|
|
100
113
|
/**
|
|
101
114
|
* How many rows two Buchungsstapel of one period do not share, compared on
|
|
102
115
|
* what a booking says (its day, amount, side, accounts, BU key, Belegfeld 1,
|
|
103
116
|
* cost centres, and whether it is a general reversal) and not on its wording or its document link. The rows are
|
|
104
|
-
* compared as a multiset: a row that stands twice in one and once in the other differs once.
|
|
105
|
-
*
|
|
106
|
-
*
|
|
117
|
+
* compared as a multiset: a row that stands twice in one and once in the other differs once. Both sides are compared
|
|
118
|
+
* as a file states them (`comparableOf`: a `"` in a text field as `'`, Belegfeld 1 as skr's writer writes it, a
|
|
119
|
+
* character Windows-1252 cannot hold as `?`), so bookings stored of rows before writing and bookings read from a
|
|
120
|
+
* file compare alike. A booking stored before 4.1, which does not record its cost centres, never differs on them (`pairBookings`); compare
|
|
121
|
+
* `bookingsOfRows` of the rows sent for an answer that counts them. A booking a Buchungsstapel cannot hold (no day,
|
|
122
|
+
* no positive amount) is refused (`invalid_bookings`).
|
|
107
123
|
*/
|
|
108
124
|
export const differingBookingCount = (leftArg, rightArg) => {
|
|
109
|
-
const { leftPaired, rightPaired } = pairBookings(leftArg, rightArg);
|
|
125
|
+
const { leftPaired, rightPaired } = pairBookings(comparableOf(leftArg), comparableOf(rightArg));
|
|
110
126
|
return [...leftPaired, ...rightPaired].filter((pairedArg) => !pairedArg).length;
|
|
111
127
|
};
|
|
112
128
|
/**
|
|
@@ -172,6 +188,8 @@ export const replacedCharactersOfRows = (rowsArg) => {
|
|
|
172
188
|
};
|
|
173
189
|
/** The file of rows: the header and the caption row, the rows, encoded in Windows-1252, with where each character stands. */
|
|
174
190
|
const fileOfRows = (rows, headerArg, filenameArg) => {
|
|
191
|
+
refuseUnwritableRows(rows);
|
|
192
|
+
refuseOutsideHeader(rows, headerArg);
|
|
175
193
|
const { csv } = plugins.skrCore.writeExtfBuchungsstapel(rows, headerArg);
|
|
176
194
|
const { bytes, replaced } = encodeWindows1252(csv);
|
|
177
195
|
// the file is the header line, the caption line and one line per row, each ending in CRLF (`writeExtfBuchungsstapel`)
|
|
@@ -197,8 +215,119 @@ const fileOfRows = (rows, headerArg, filenameArg) => {
|
|
|
197
215
|
}
|
|
198
216
|
return { ...replacedArg, row, field: fieldAt(fieldStartsOf(rowLines[row]), replacedArg.offset - lineStarts[row]) };
|
|
199
217
|
});
|
|
200
|
-
|
|
218
|
+
// the bookings of what was written, as the file states them
|
|
219
|
+
const written = plugins.skrCore.readExtfBuchungsstapel(bytes).rows;
|
|
220
|
+
if (written.length !== rows.length) {
|
|
221
|
+
throw new CompatibilityError('export_failed', `${rows.length} row(s) written, ${written.length} read back`);
|
|
222
|
+
}
|
|
223
|
+
return { filename: filenameArg, csv, bytes, rows, bookings: bookingsOfRows(written), replacedCharacters };
|
|
224
|
+
};
|
|
225
|
+
/** The Belegdatum of a row as its day, midnight UTC, in epoch milliseconds. */
|
|
226
|
+
const dayOfRow = (rowArg) => Date.UTC(rowArg.belegDatum.getUTCFullYear(), rowArg.belegDatum.getUTCMonth(), rowArg.belegDatum.getUTCDate());
|
|
227
|
+
/** A row as a refusal names it: its place among the rows given, its day, amount, side, accounts and Belegfeld 1. */
|
|
228
|
+
const rowNameOf = (rowArg, indexArg) => `row ${indexArg + 1} (${Number.isNaN(rowArg.belegDatum.getTime()) ? 'no day' : rowArg.belegDatum.toISOString().slice(0, 10)}, ${rowArg.umsatzCents} ${rowArg.sollHaben} ${rowArg.konto}/${rowArg.gegenKonto}`
|
|
229
|
+
+ `${rowArg.belegfeld1 ? `, Belegfeld 1 ${rowArg.belegfeld1}` : ''})`;
|
|
230
|
+
/**
|
|
231
|
+
* Refuses a row a Buchungsstapel does not hold, before anything is written: a Belegdatum that is no day, and an
|
|
232
|
+
* amount that is not a positive whole number of cents (a Buchungsstapel states the side apart, field 2, and
|
|
233
|
+
* `readExtfBuchungsstapel` refuses any other). `invalid_bookings`, naming the row.
|
|
234
|
+
*/
|
|
235
|
+
const refuseUnwritableRows = (rowsArg) => {
|
|
236
|
+
rowsArg.forEach((rowArg, indexArg) => {
|
|
237
|
+
if (Number.isNaN(rowArg.belegDatum.getTime())) {
|
|
238
|
+
throw new CompatibilityError('invalid_bookings', `${rowNameOf(rowArg, indexArg)} has no Belegdatum`);
|
|
239
|
+
}
|
|
240
|
+
if (!Number.isSafeInteger(rowArg.umsatzCents) || rowArg.umsatzCents <= 0) {
|
|
241
|
+
throw new CompatibilityError('invalid_bookings', `${rowNameOf(rowArg, indexArg)}: a Buchungsstapel states a positive amount, the side apart`);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
201
244
|
};
|
|
245
|
+
/**
|
|
246
|
+
* Refuses a header whose period a Buchungsstapel cannot state (`invalid_header`): Datum von after Datum bis, or a
|
|
247
|
+
* period that does not lie within the one Wirtschaftsjahr beginning on the Wirtschaftsjahr-Beginn (a Belegdatum is
|
|
248
|
+
* written TTMM, and the reader takes its year from them); and every row whose Belegdatum lies outside the period
|
|
249
|
+
* (`invalid_bookings`, naming it). Checked before anything is written.
|
|
250
|
+
*/
|
|
251
|
+
const refuseOutsideHeader = (rowsArg, headerArg) => {
|
|
252
|
+
const day = (dateArg) => Date.UTC(dateArg.getUTCFullYear(), dateArg.getUTCMonth(), dateArg.getUTCDate());
|
|
253
|
+
const from = day(headerArg.dateFrom);
|
|
254
|
+
const to = day(headerArg.dateTo);
|
|
255
|
+
const start = day(headerArg.fiscalYearStart);
|
|
256
|
+
const end = Date.UTC(headerArg.fiscalYearStart.getUTCFullYear() + 1, headerArg.fiscalYearStart.getUTCMonth(), headerArg.fiscalYearStart.getUTCDate());
|
|
257
|
+
const iso = (timeArg) => new Date(timeArg).toISOString().slice(0, 10);
|
|
258
|
+
if ([from, to, start].some(Number.isNaN)) {
|
|
259
|
+
throw new CompatibilityError('invalid_header', 'the header states no day for the Wirtschaftsjahr-Beginn, Datum von or Datum bis');
|
|
260
|
+
}
|
|
261
|
+
if (to < from) {
|
|
262
|
+
throw new CompatibilityError('invalid_header', `the period of the header ends (${iso(to)}) before it begins (${iso(from)})`);
|
|
263
|
+
}
|
|
264
|
+
if (from < start || to >= end) {
|
|
265
|
+
throw new CompatibilityError('invalid_header', `the period of the header, ${iso(from)} to ${iso(to)}, does not lie within the Wirtschaftsjahr beginning ${iso(start)}`);
|
|
266
|
+
}
|
|
267
|
+
rowsArg.forEach((rowArg, indexArg) => {
|
|
268
|
+
const time = dayOfRow(rowArg);
|
|
269
|
+
if (time < from || time > to) {
|
|
270
|
+
throw new CompatibilityError('invalid_bookings', `${rowNameOf(rowArg, indexArg)} lies outside the period of the header, ${iso(from)} to ${iso(to)}`);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
/**
|
|
275
|
+
* Rows as a Buchungsstapel file states them: each row written by the writer (`@fin.cx/skr` `writeExtfBuchungsstapel`,
|
|
276
|
+
* which writes a `"` in a text field as `'` and cuts a field to its DATEV length), encoded in Windows-1252 (a
|
|
277
|
+
* character it cannot hold written `?`, `encodeWindows1252`), and read back (`@fin.cx/skr` `readExtfBuchungsstapel`),
|
|
278
|
+
* in the order given. Every rule of the writer, the encoding and the reader applies because the rows go through them,
|
|
279
|
+
* not through a copy of their rules. The rows of each calendar year are written as one file whose header spans their
|
|
280
|
+
* days; the header states nothing a row is read by beyond its days. A row the writer or the reader refuses throws as
|
|
281
|
+
* it does.
|
|
282
|
+
*/
|
|
283
|
+
export const rowsAsWritten = (rowsArg) => {
|
|
284
|
+
refuseUnwritableRows(rowsArg);
|
|
285
|
+
const written = new Array(rowsArg.length);
|
|
286
|
+
// the indexes of the rows of each calendar year, and the first and last day among them
|
|
287
|
+
const years = new Map();
|
|
288
|
+
rowsArg.forEach((rowArg, indexArg) => {
|
|
289
|
+
const year = rowArg.belegDatum.getUTCFullYear();
|
|
290
|
+
const time = dayOfRow(rowArg);
|
|
291
|
+
const group = years.get(year);
|
|
292
|
+
if (group) {
|
|
293
|
+
group.indexes.push(indexArg);
|
|
294
|
+
group.first = Math.min(group.first, time);
|
|
295
|
+
group.last = Math.max(group.last, time);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
years.set(year, { indexes: [indexArg], first: time, last: time });
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
for (const [year, group] of years) {
|
|
302
|
+
const { csv } = plugins.skrCore.writeExtfBuchungsstapel(group.indexes.map((indexArg) => rowsArg[indexArg]), {
|
|
303
|
+
createdAt: new Date(Date.UTC(year, 0, 1)),
|
|
304
|
+
consultantNumber: 0,
|
|
305
|
+
clientNumber: 0,
|
|
306
|
+
// a Belegdatum is written TTMM: the reader takes its year from the Wirtschaftsjahr and the period of the header
|
|
307
|
+
fiscalYearStart: new Date(Date.UTC(year, 0, 1)),
|
|
308
|
+
dateFrom: new Date(group.first),
|
|
309
|
+
dateTo: new Date(group.last),
|
|
310
|
+
label: '',
|
|
311
|
+
festschreibung: false,
|
|
312
|
+
});
|
|
313
|
+
const read = plugins.skrCore.readExtfBuchungsstapel(encodeWindows1252(csv).bytes).rows;
|
|
314
|
+
if (read.length !== group.indexes.length) {
|
|
315
|
+
throw new CompatibilityError('export_failed', `${group.indexes.length} row(s) written, ${read.length} read back`);
|
|
316
|
+
}
|
|
317
|
+
group.indexes.forEach((indexArg, positionArg) => {
|
|
318
|
+
written[indexArg] = read[positionArg];
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
return written;
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* The bookings of rows as a Buchungsstapel file states them (`rowsAsWritten`): what a file handed over, read back
|
|
325
|
+
* with `readExtfBuchungsstapel`, is compared with. `bookingsOfRows` of the rows before writing keeps what the file
|
|
326
|
+
* does not (a Belegfeld 1 the writer changes: cut to 36 characters before skr 7.3.0, mapped since where DATEV does
|
|
327
|
+
* not take it; a character Windows-1252 cannot hold), and Belegfeld 1 is compared, so such a booking would differ
|
|
328
|
+
* from the file forever.
|
|
329
|
+
*/
|
|
330
|
+
export const bookingsAsWritten = (rowsArg) => bookingsOfRows(rowsAsWritten(rowsArg));
|
|
202
331
|
/** Writes a Buchungsstapel: the rows of the drafts, the header and the caption row, encoded in Windows-1252. */
|
|
203
332
|
export const writeBuchungsstapel = (optionsArg) => fileOfRows(datevRowsOf(optionsArg.drafts, optionsArg.policy), optionsArg.header, optionsArg.filename);
|
|
204
333
|
/**
|
|
@@ -241,12 +370,15 @@ const refuseCostCentresUnknown = (handedOverArg) => {
|
|
|
241
370
|
* handed over that the current ones no longer hold (`reversed`, each once for each time it is missing), the ones they
|
|
242
371
|
* still hold (`kept`, as they were handed over) and the current rows the bookings handed over do not hold (`added`),
|
|
243
372
|
* each in its order. A booking that stands in both is kept: a changed text or document link is no changed booking,
|
|
244
|
-
* a changed cost centre is.
|
|
245
|
-
*
|
|
373
|
+
* a changed cost centre is. The current rows are compared as a file states them (`bookingsAsWritten`), as the
|
|
374
|
+
* bookings handed over are; `added` are the rows themselves, which the writer writes. A booking handed over whose
|
|
375
|
+
* cost centres its record does not state (stored before 4.1) is refused (`handed_over_cost_centres_unknown`): pass
|
|
376
|
+
* `bookingsOfRows` of the rows sent instead.
|
|
246
377
|
*/
|
|
247
378
|
export const correctionOf = (handedOverArg, currentArg) => {
|
|
248
379
|
refuseCostCentresUnknown(handedOverArg);
|
|
249
|
-
|
|
380
|
+
// the current rows as a file states them, as the state handed over was: a reference the writer changes is the same
|
|
381
|
+
const { leftPaired, rightPaired } = pairBookings(comparableOf(handedOverArg), bookingsAsWritten(currentArg));
|
|
250
382
|
return {
|
|
251
383
|
reversed: handedOverArg.filter((_bookingArg, indexArg) => !leftPaired[indexArg]),
|
|
252
384
|
kept: handedOverArg.filter((_bookingArg, indexArg) => leftPaired[indexArg]),
|
|
@@ -263,7 +395,8 @@ export const correctionOf = (handedOverArg, currentArg) => {
|
|
|
263
395
|
* twice or not at all; `handed_over_cost_centres_unknown` for a booking whose cost centres are not known.
|
|
264
396
|
*/
|
|
265
397
|
export const writeCorrectionBuchungsstapel = (optionsArg) => {
|
|
266
|
-
|
|
398
|
+
// rows read back from the file sent are as written already; rows given to the writer become what it wrote
|
|
399
|
+
const handedOver = optionsArg.handedOverRows !== undefined ? bookingsAsWritten(optionsArg.handedOverRows) : optionsArg.handedOver;
|
|
267
400
|
if (handedOver === undefined || (optionsArg.handedOver !== undefined && optionsArg.handedOverRows !== undefined)) {
|
|
268
401
|
throw new CompatibilityError('invalid_bookings', 'pass the state handed over once: the bookings stored (handedOver) or the rows sent (handedOverRows)');
|
|
269
402
|
}
|
|
@@ -277,6 +410,8 @@ export const writeCorrectionBuchungsstapel = (optionsArg) => {
|
|
|
277
410
|
throw new CompatibilityError('nothing_to_correct', 'the bookings of the period are the ones handed over; there is nothing to correct');
|
|
278
411
|
}
|
|
279
412
|
const rows = [...reversed.map((bookingArg) => ({ ...rowOfBooking(bookingArg), generalumkehr: true })), ...added];
|
|
280
|
-
|
|
413
|
+
const file = fileOfRows(rows, optionsArg.header, optionsArg.filename);
|
|
414
|
+
// the rows booked anew as the correction file states them, after the reversals
|
|
415
|
+
return { ...file, reversed, added, bookingsAfter: [...kept, ...file.bookings.slice(reversed.length)] };
|
|
281
416
|
};
|
|
282
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9leHRmL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNqRCxPQUFPLEVBQUUsaUJBQWlCLEVBQTJCLE1BQU0sc0JBQXNCLENBQUM7QUFFbEYsT0FBTyxFQUFFLGtCQUFrQixFQUFnQyxNQUFNLGFBQWEsQ0FBQztBQUsvRSxzRkFBc0Y7QUFDdEYsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcsZ0NBQWdDLENBQUM7QUFFbEUsd0ZBQXdGO0FBQ3hGLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxDQUFDLFFBQWdCLEVBQVUsRUFBRSxDQUFDLHVCQUF1QixRQUFRLE1BQU0sQ0FBQztBQStCaEcsMEVBQTBFO0FBQzFFLE1BQU0sVUFBVSxHQUFHLENBQUMsT0FBZSxFQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0FBRWxILDRDQUE0QztBQUM1QyxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxPQUEyQyxFQUFvQixFQUFFLENBQzlGLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdkIsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO0lBQy9CLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUztJQUMzQixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7SUFDbkIsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO0lBQzdCLEtBQUssRUFBRSxNQUFNLENBQUMsWUFBWTtJQUMxQixJQUFJLEVBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVB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
|
|
417
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9leHRmL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNqRCxPQUFPLEVBQUUsaUJBQWlCLEVBQTJCLE1BQU0sc0JBQXNCLENBQUM7QUFFbEYsT0FBTyxFQUFFLGtCQUFrQixFQUFnQyxNQUFNLGFBQWEsQ0FBQztBQUsvRSxzRkFBc0Y7QUFDdEYsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcsZ0NBQWdDLENBQUM7QUFFbEUsd0ZBQXdGO0FBQ3hGLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxDQUFDLFFBQWdCLEVBQVUsRUFBRSxDQUFDLHVCQUF1QixRQUFRLE1BQU0sQ0FBQztBQStCaEcsMEVBQTBFO0FBQzFFLE1BQU0sVUFBVSxHQUFHLENBQUMsT0FBZSxFQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0FBRWxILDRDQUE0QztBQUM1QyxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxPQUEyQyxFQUFvQixFQUFFLENBQzlGLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdkIsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO0lBQy9CLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUztJQUMzQixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7SUFDbkIsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO0lBQzdCLEtBQUssRUFBRSxNQUFNLENBQUMsWUFBWTtJQUMxQixJQUFJLEVBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVB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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fin.cx/compatibility",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Exchange formats of third-party accounting systems: the EXTF Buchungsstapel in Windows-1252 on the rows of @fin.cx/skr, and the document-image archive (document.xml and ZIP)",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@push.rocks/smartarchive": "^5.4.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@fin.cx/skr": "^
|
|
48
|
+
"@fin.cx/skr": "^7.3.0",
|
|
49
49
|
"@git.zone/tsbuild": "^5.0.0",
|
|
50
50
|
"@git.zone/tsrun": "^3.0.2",
|
|
51
51
|
"@git.zone/tstest": "^6.3.2",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"license.md"
|
|
59
59
|
],
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@fin.cx/skr": "^
|
|
61
|
+
"@fin.cx/skr": "^7.0.1"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"test": "(tstest test/ --verbose)",
|
package/readme.md
CHANGED
|
@@ -17,7 +17,7 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
|
|
|
17
17
|
pnpm install @fin.cx/compatibility @fin.cx/skr
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
`@fin.cx/skr` (^
|
|
20
|
+
`@fin.cx/skr` (^7.0.1) is a peer dependency: the drafts and the account policy the EXTF writer takes are built by your copy of skr, and the writer turns them into rows with the same copy, so the rows follow the chart the drafts were booked on (which accounts are Automatikkonten, which carry VAT). A second copy of skr of another major would write rows by another chart; a package manager that finds your skr outside the range says so as an unmet peer.
|
|
21
21
|
|
|
22
22
|
## Usage
|
|
23
23
|
|
|
@@ -42,7 +42,7 @@ const file = extf.writeBuchungsstapel({
|
|
|
42
42
|
filename: extf.extfFilename('2026-03'), // EXTF_Buchungsstapel_2026-03.csv
|
|
43
43
|
});
|
|
44
44
|
file.bytes; // Uint8Array in Windows-1252, served as extf.EXTF_CONTENT_TYPE
|
|
45
|
-
file.bookings; // what each row says, for keeping and comparing
|
|
45
|
+
file.bookings; // what each row says as the file states it, for keeping and comparing
|
|
46
46
|
file.replacedCharacters; // [{ offset, character: 'ő', row: 1, field: 14 }, …]: written as "?"
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -50,11 +50,14 @@ file.replacedCharacters; // [{ offset, character: 'ő', row: 1, field: 14 }, …
|
|
|
50
50
|
- **The same without a file.** `extf.replacedCharactersOfRows(rows)` names the characters of each row the file could not hold (`{ row, field, character }`), without a header and without writing anything: for a preview, before the consultant and client numbers of the header are known. It reads each row's line as the writer writes it (`@fin.cx/skr` `datevRowFields`), so a character a field is cut off before (the Buchungstext keeps 60 characters) is not named.
|
|
51
51
|
|
|
52
52
|
- **A draft the account policy refuses** throws `CompatibilityError` with code `invalid_bookings` and a message naming the draft.
|
|
53
|
+
- **What the reader would refuse is refused before writing.** A header whose period ends before it begins or leaves the Wirtschaftsjahr beginning on its Wirtschaftsjahr-Beginn throws code `invalid_header`; a row whose Belegdatum lies outside that period, is no day, or whose amount is not positive throws `invalid_bookings`, naming the row.
|
|
53
54
|
- **A failed conversion** throws code `export_failed`.
|
|
54
55
|
- **A document-image archive DATEV would not take** (no document, a GUID of another form, a format it does not take) throws code `invalid_documents`.
|
|
55
56
|
- **`differingBookingCount(left, right)`** counts the rows two Stapel of one period do not share. It compares each booking's day, amount, side, accounts, BU key, Belegfeld 1, cost centres (KOST1, KOST2) and whether it is a general reversal, as a multiset, and ignores wording and document links. A booking stored before 4.1 has no cost-centre fields: its record says nothing of them, and they never make it differ; compare `bookingsOfRows` of the rows sent for an answer that counts them.
|
|
56
|
-
- **
|
|
57
|
-
- **
|
|
57
|
+
- **The bookings as the file states them.** `extf.bookingsAsWritten(rows)` (and `extf.rowsAsWritten(rows)`) writes the rows with skr's writer, encodes them in Windows-1252 and reads them back with skr's reader: a `"` in a text field becomes `'`, Belegfeld 1 is written as skr's writer writes it (cut to 36 characters before skr 7.3.0; since then a value DATEV does not take is mapped, `datevBelegfeldOf`, with the original in a Beleginfo), a line break becomes a space and a character Windows-1252 cannot hold becomes `?`, as in the file. `writeBuchungsstapel`'s `bookings` are read back from the bytes it wrote. `differingBookingCount` and a correction take both sides as a file states them, so bookings stored before writing (4.1 and before), bookings of this version and rows read back from the file sent compare alike; compare with them, not with `bookingsOfRows` of rows that were not written, which keep what the file does not.
|
|
58
|
+
- **A period whose bookings were stored before 4.1.** Such bookings record no cost centres, although the Stapel sent stated them (fields 37 and 38), and `differingBookingCount` never counts them as differing on cost centres alone: a change of a cost centre only is not seen. For such a period read the file handed over back (`readExtfBuchungsstapel(bytes).rows`) and compare `bookingsOfRows` of those rows, or pass them to a correction as `handedOverRows`.
|
|
59
|
+
- **A correction of a period handed over.** `writeCorrectionBuchungsstapel({ handedOver, drafts, policy, header, filename })` writes only what changed since the state handed over: each booking handed over that the drafts no longer hold is written again with field 118 "Generalumkehr" set, so DATEV takes it back on its own side and day, then each row of the drafts that was not handed over; what stands in both is not written. A changed text or document link is no change; a changed cost centre is, so the booking is taken back on the cost centre DATEV received and booked on the new one. Every row keeps its Belegdatum, so it counts in the period it belongs to; a booking handed over is never replaced (§ 146 Abs. 4 AO), which also holds once DATEV has fixed the period (Festschreibung). The file names what it takes back (`reversed`), what it books (`added`) and the bookings after it (`bookingsAfter`: each booking it keeps as it was handed over, text and document link included, then the rows it books anew as the correction file states them). Both sides are compared as a file states them, so a reference the writer changes (a `"`, more than 36 characters, a character Windows-1252 cannot hold, a line break) is no change. `correctionOf(handedOver, rows)` gives `reversed`, `kept` and `added` without a file, and `rowOfBooking(booking)` the row a booking was written as.
|
|
60
|
+
- **The state handed over** is given once: the bookings stored of it (`handedOver`: the `bookings` of its Buchungsstapel as they were stored, by this version or by 4.1, or the last correction's `bookingsAfter`), or the rows of the Stapel as it was sent (`handedOverRows`: the transmitted file read back with `@fin.cx/skr` `readExtfBuchungsstapel(bytes).rows`, or the `rows` given to the writer). Every form compares alike. A booking stored before 4.1 has no cost-centre fields, although the Stapel sent stated them (fields 37 and 38): a correction refuses it with code `handed_over_cost_centres_unknown`, naming it, since whether it must be taken back turns on the cost centres DATEV holds and a reversal without them would not mirror it; pass `handedOverRows` for such a period. Nothing changed is refused with `nothing_to_correct`; a general reversal in the state handed over (a correction file passed as the state), or a state given twice or not at all, with `invalid_bookings`.
|
|
58
61
|
- **A booking keeps its general reversal** (`IExportBooking.generalumkehr`, from field 118) and its cost centres (`kost1`, `kost2`, empty where the row states none).
|
|
59
62
|
|
|
60
63
|
```typescript
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@fin.cx/compatibility',
|
|
6
|
-
version: '
|
|
6
|
+
version: '5.0.1',
|
|
7
7
|
description: 'Exchange formats of third-party accounting systems: the EXTF Buchungsstapel in Windows-1252 on the rows of @fin.cx/skr, and the document-image archive (document.xml and ZIP)'
|
|
8
8
|
}
|
package/ts/error.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Why an exchange file could not be written:
|
|
3
|
-
* - `invalid_bookings`: a draft the account policy refuses, the message names it;
|
|
4
|
-
* bookings handed over to a correction Buchungsstapel (a correction file passed as the state handed over);
|
|
3
|
+
* - `invalid_bookings`: a draft the account policy refuses, the message names it; a general reversal among the
|
|
4
|
+
* bookings handed over to a correction Buchungsstapel (a correction file passed as the state handed over); or a row
|
|
5
|
+
* or booking a Buchungsstapel does not hold (no day, an amount that is not positive) or whose Belegdatum lies
|
|
6
|
+
* outside the period of the header, named;
|
|
7
|
+
* - `invalid_header`: a header whose period ends before it begins or does not lie within the one Wirtschaftsjahr
|
|
8
|
+
* beginning on its Wirtschaftsjahr-Beginn;
|
|
5
9
|
* - `export_failed`: the conversion into rows failed;
|
|
6
10
|
* - `invalid_documents`: a document of a document-image archive DATEV does not take (its GUID, its format), or none;
|
|
7
11
|
* - `nothing_to_correct`: a correction Buchungsstapel whose current bookings are the ones handed over;
|
|
8
12
|
* - `handed_over_cost_centres_unknown`: a correction of a period whose bookings handed over include one whose cost
|
|
9
13
|
* centres its record does not state (stored before 4.1) and no rows sent were given; the message names it.
|
|
10
14
|
*/
|
|
11
|
-
export type TCompatibilityErrorCode = 'invalid_bookings' | 'export_failed' | 'invalid_documents' | 'nothing_to_correct' | 'handed_over_cost_centres_unknown';
|
|
15
|
+
export type TCompatibilityErrorCode = 'invalid_bookings' | 'invalid_header' | 'export_failed' | 'invalid_documents' | 'nothing_to_correct' | 'handed_over_cost_centres_unknown';
|
|
12
16
|
|
|
13
17
|
export class CompatibilityError extends Error {
|
|
14
18
|
public readonly code: TCompatibilityErrorCode;
|
package/ts/extf/index.ts
CHANGED
|
@@ -144,16 +144,34 @@ const pairBookings = (
|
|
|
144
144
|
return { leftPaired, rightPaired };
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Bookings as a Buchungsstapel file states them, for comparing: each written as the row it was written as
|
|
149
|
+
* (`rowOfBooking`) and read back (`bookingsAsWritten`), so bookings stored of rows before writing (4.1 and before)
|
|
150
|
+
* and bookings read from a file compare alike. One that records no cost centres (stored before 4.1) keeps recording
|
|
151
|
+
* none, so it still never differs on them. A booking a Buchungsstapel cannot hold is refused (`invalid_bookings`).
|
|
152
|
+
*/
|
|
153
|
+
const comparableOf = (bookingsArg: readonly IExportBooking[]): IExportBooking[] =>
|
|
154
|
+
bookingsAsWritten(bookingsArg.map((bookingArg) => rowOfBooking(bookingArg))).map((bookingArg, indexArg) => {
|
|
155
|
+
if (recordsCostCentres(bookingsArg[indexArg])) {
|
|
156
|
+
return bookingArg;
|
|
157
|
+
}
|
|
158
|
+
const { kost1: _kost1, kost2: _kost2, ...unrecorded } = bookingArg;
|
|
159
|
+
return unrecorded;
|
|
160
|
+
});
|
|
161
|
+
|
|
147
162
|
/**
|
|
148
163
|
* How many rows two Buchungsstapel of one period do not share, compared on
|
|
149
164
|
* what a booking says (its day, amount, side, accounts, BU key, Belegfeld 1,
|
|
150
165
|
* cost centres, and whether it is a general reversal) and not on its wording or its document link. The rows are
|
|
151
|
-
* compared as a multiset: a row that stands twice in one and once in the other differs once.
|
|
152
|
-
*
|
|
153
|
-
*
|
|
166
|
+
* compared as a multiset: a row that stands twice in one and once in the other differs once. Both sides are compared
|
|
167
|
+
* as a file states them (`comparableOf`: a `"` in a text field as `'`, Belegfeld 1 as skr's writer writes it, a
|
|
168
|
+
* character Windows-1252 cannot hold as `?`), so bookings stored of rows before writing and bookings read from a
|
|
169
|
+
* file compare alike. A booking stored before 4.1, which does not record its cost centres, never differs on them (`pairBookings`); compare
|
|
170
|
+
* `bookingsOfRows` of the rows sent for an answer that counts them. A booking a Buchungsstapel cannot hold (no day,
|
|
171
|
+
* no positive amount) is refused (`invalid_bookings`).
|
|
154
172
|
*/
|
|
155
173
|
export const differingBookingCount = (leftArg: readonly IExportBooking[], rightArg: readonly IExportBooking[]): number => {
|
|
156
|
-
const { leftPaired, rightPaired } = pairBookings(leftArg, rightArg);
|
|
174
|
+
const { leftPaired, rightPaired } = pairBookings(comparableOf(leftArg), comparableOf(rightArg));
|
|
157
175
|
return [...leftPaired, ...rightPaired].filter((pairedArg) => !pairedArg).length;
|
|
158
176
|
};
|
|
159
177
|
|
|
@@ -258,7 +276,15 @@ export interface IBuchungsstapelFile {
|
|
|
258
276
|
csv: string;
|
|
259
277
|
/** the file in Windows-1252, as it is handed over */
|
|
260
278
|
bytes: Uint8Array;
|
|
279
|
+
/** the rows as they were given to the writer; the file states them as `rowsAsWritten` does */
|
|
261
280
|
rows: IDatevBuchungsstapelRow[];
|
|
281
|
+
/**
|
|
282
|
+
* The bookings the file states, read back from its bytes (`@fin.cx/skr` `readExtfBuchungsstapel`): a `"` in a
|
|
283
|
+
* text field as `'`, Belegfeld 1 as skr's writer writes it (cut to 36 characters before skr 7.3.0; since then a value
|
|
284
|
+
* DATEV does not take mapped, `datevBelegfeldOf`), a character Windows-1252 cannot hold as `?`. What a file
|
|
285
|
+
* read back is compared with, and what a correction's `handedOver` is (4.1 and before: the rows' bookings before
|
|
286
|
+
* writing).
|
|
287
|
+
*/
|
|
262
288
|
bookings: IExportBooking[];
|
|
263
289
|
/** the characters Windows-1252 cannot write, each written as `?`, with the row and field it stands in */
|
|
264
290
|
replacedCharacters: IBuchungsstapelReplacement[];
|
|
@@ -266,6 +292,8 @@ export interface IBuchungsstapelFile {
|
|
|
266
292
|
|
|
267
293
|
/** The file of rows: the header and the caption row, the rows, encoded in Windows-1252, with where each character stands. */
|
|
268
294
|
const fileOfRows = (rows: IDatevBuchungsstapelRow[], headerArg: IDatevExtfHeaderOptions, filenameArg: string): IBuchungsstapelFile => {
|
|
295
|
+
refuseUnwritableRows(rows);
|
|
296
|
+
refuseOutsideHeader(rows, headerArg);
|
|
269
297
|
const { csv } = plugins.skrCore.writeExtfBuchungsstapel(rows, headerArg);
|
|
270
298
|
const { bytes, replaced } = encodeWindows1252(csv);
|
|
271
299
|
// the file is the header line, the caption line and one line per row, each ending in CRLF (`writeExtfBuchungsstapel`)
|
|
@@ -291,9 +319,127 @@ const fileOfRows = (rows: IDatevBuchungsstapelRow[], headerArg: IDatevExtfHeader
|
|
|
291
319
|
}
|
|
292
320
|
return { ...replacedArg, row, field: fieldAt(fieldStartsOf(rowLines[row]), replacedArg.offset - lineStarts[row]) };
|
|
293
321
|
});
|
|
294
|
-
|
|
322
|
+
// the bookings of what was written, as the file states them
|
|
323
|
+
const written = plugins.skrCore.readExtfBuchungsstapel(bytes).rows;
|
|
324
|
+
if (written.length !== rows.length) {
|
|
325
|
+
throw new CompatibilityError('export_failed', `${rows.length} row(s) written, ${written.length} read back`);
|
|
326
|
+
}
|
|
327
|
+
return { filename: filenameArg, csv, bytes, rows, bookings: bookingsOfRows(written), replacedCharacters };
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/** The Belegdatum of a row as its day, midnight UTC, in epoch milliseconds. */
|
|
331
|
+
const dayOfRow = (rowArg: IDatevBuchungsstapelRow): number =>
|
|
332
|
+
Date.UTC(rowArg.belegDatum.getUTCFullYear(), rowArg.belegDatum.getUTCMonth(), rowArg.belegDatum.getUTCDate());
|
|
333
|
+
|
|
334
|
+
/** A row as a refusal names it: its place among the rows given, its day, amount, side, accounts and Belegfeld 1. */
|
|
335
|
+
const rowNameOf = (rowArg: IDatevBuchungsstapelRow, indexArg: number): string =>
|
|
336
|
+
`row ${indexArg + 1} (${Number.isNaN(rowArg.belegDatum.getTime()) ? 'no day' : rowArg.belegDatum.toISOString().slice(0, 10)}, ${rowArg.umsatzCents} ${rowArg.sollHaben} ${rowArg.konto}/${rowArg.gegenKonto}`
|
|
337
|
+
+ `${rowArg.belegfeld1 ? `, Belegfeld 1 ${rowArg.belegfeld1}` : ''})`;
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Refuses a row a Buchungsstapel does not hold, before anything is written: a Belegdatum that is no day, and an
|
|
341
|
+
* amount that is not a positive whole number of cents (a Buchungsstapel states the side apart, field 2, and
|
|
342
|
+
* `readExtfBuchungsstapel` refuses any other). `invalid_bookings`, naming the row.
|
|
343
|
+
*/
|
|
344
|
+
const refuseUnwritableRows = (rowsArg: readonly IDatevBuchungsstapelRow[]): void => {
|
|
345
|
+
rowsArg.forEach((rowArg, indexArg) => {
|
|
346
|
+
if (Number.isNaN(rowArg.belegDatum.getTime())) {
|
|
347
|
+
throw new CompatibilityError('invalid_bookings', `${rowNameOf(rowArg, indexArg)} has no Belegdatum`);
|
|
348
|
+
}
|
|
349
|
+
if (!Number.isSafeInteger(rowArg.umsatzCents) || rowArg.umsatzCents <= 0) {
|
|
350
|
+
throw new CompatibilityError('invalid_bookings', `${rowNameOf(rowArg, indexArg)}: a Buchungsstapel states a positive amount, the side apart`);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
295
353
|
};
|
|
296
354
|
|
|
355
|
+
/**
|
|
356
|
+
* Refuses a header whose period a Buchungsstapel cannot state (`invalid_header`): Datum von after Datum bis, or a
|
|
357
|
+
* period that does not lie within the one Wirtschaftsjahr beginning on the Wirtschaftsjahr-Beginn (a Belegdatum is
|
|
358
|
+
* written TTMM, and the reader takes its year from them); and every row whose Belegdatum lies outside the period
|
|
359
|
+
* (`invalid_bookings`, naming it). Checked before anything is written.
|
|
360
|
+
*/
|
|
361
|
+
const refuseOutsideHeader = (rowsArg: readonly IDatevBuchungsstapelRow[], headerArg: IDatevExtfHeaderOptions): void => {
|
|
362
|
+
const day = (dateArg: Date): number => Date.UTC(dateArg.getUTCFullYear(), dateArg.getUTCMonth(), dateArg.getUTCDate());
|
|
363
|
+
const from = day(headerArg.dateFrom);
|
|
364
|
+
const to = day(headerArg.dateTo);
|
|
365
|
+
const start = day(headerArg.fiscalYearStart);
|
|
366
|
+
const end = Date.UTC(headerArg.fiscalYearStart.getUTCFullYear() + 1, headerArg.fiscalYearStart.getUTCMonth(), headerArg.fiscalYearStart.getUTCDate());
|
|
367
|
+
const iso = (timeArg: number): string => new Date(timeArg).toISOString().slice(0, 10);
|
|
368
|
+
if ([from, to, start].some(Number.isNaN)) {
|
|
369
|
+
throw new CompatibilityError('invalid_header', 'the header states no day for the Wirtschaftsjahr-Beginn, Datum von or Datum bis');
|
|
370
|
+
}
|
|
371
|
+
if (to < from) {
|
|
372
|
+
throw new CompatibilityError('invalid_header', `the period of the header ends (${iso(to)}) before it begins (${iso(from)})`);
|
|
373
|
+
}
|
|
374
|
+
if (from < start || to >= end) {
|
|
375
|
+
throw new CompatibilityError('invalid_header', `the period of the header, ${iso(from)} to ${iso(to)}, does not lie within the Wirtschaftsjahr beginning ${iso(start)}`);
|
|
376
|
+
}
|
|
377
|
+
rowsArg.forEach((rowArg, indexArg) => {
|
|
378
|
+
const time = dayOfRow(rowArg);
|
|
379
|
+
if (time < from || time > to) {
|
|
380
|
+
throw new CompatibilityError('invalid_bookings', `${rowNameOf(rowArg, indexArg)} lies outside the period of the header, ${iso(from)} to ${iso(to)}`);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Rows as a Buchungsstapel file states them: each row written by the writer (`@fin.cx/skr` `writeExtfBuchungsstapel`,
|
|
387
|
+
* which writes a `"` in a text field as `'` and cuts a field to its DATEV length), encoded in Windows-1252 (a
|
|
388
|
+
* character it cannot hold written `?`, `encodeWindows1252`), and read back (`@fin.cx/skr` `readExtfBuchungsstapel`),
|
|
389
|
+
* in the order given. Every rule of the writer, the encoding and the reader applies because the rows go through them,
|
|
390
|
+
* not through a copy of their rules. The rows of each calendar year are written as one file whose header spans their
|
|
391
|
+
* days; the header states nothing a row is read by beyond its days. A row the writer or the reader refuses throws as
|
|
392
|
+
* it does.
|
|
393
|
+
*/
|
|
394
|
+
export const rowsAsWritten = (rowsArg: readonly IDatevBuchungsstapelRow[]): IDatevBuchungsstapelRow[] => {
|
|
395
|
+
refuseUnwritableRows(rowsArg);
|
|
396
|
+
const written: IDatevBuchungsstapelRow[] = new Array(rowsArg.length);
|
|
397
|
+
// the indexes of the rows of each calendar year, and the first and last day among them
|
|
398
|
+
const years = new Map<number, { indexes: number[]; first: number; last: number }>();
|
|
399
|
+
rowsArg.forEach((rowArg, indexArg) => {
|
|
400
|
+
const year = rowArg.belegDatum.getUTCFullYear();
|
|
401
|
+
const time = dayOfRow(rowArg);
|
|
402
|
+
const group = years.get(year);
|
|
403
|
+
if (group) {
|
|
404
|
+
group.indexes.push(indexArg);
|
|
405
|
+
group.first = Math.min(group.first, time);
|
|
406
|
+
group.last = Math.max(group.last, time);
|
|
407
|
+
} else {
|
|
408
|
+
years.set(year, { indexes: [indexArg], first: time, last: time });
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
for (const [year, group] of years) {
|
|
412
|
+
const { csv } = plugins.skrCore.writeExtfBuchungsstapel(group.indexes.map((indexArg) => rowsArg[indexArg]), {
|
|
413
|
+
createdAt: new Date(Date.UTC(year, 0, 1)),
|
|
414
|
+
consultantNumber: 0,
|
|
415
|
+
clientNumber: 0,
|
|
416
|
+
// a Belegdatum is written TTMM: the reader takes its year from the Wirtschaftsjahr and the period of the header
|
|
417
|
+
fiscalYearStart: new Date(Date.UTC(year, 0, 1)),
|
|
418
|
+
dateFrom: new Date(group.first),
|
|
419
|
+
dateTo: new Date(group.last),
|
|
420
|
+
label: '',
|
|
421
|
+
festschreibung: false,
|
|
422
|
+
});
|
|
423
|
+
const read = plugins.skrCore.readExtfBuchungsstapel(encodeWindows1252(csv).bytes).rows;
|
|
424
|
+
if (read.length !== group.indexes.length) {
|
|
425
|
+
throw new CompatibilityError('export_failed', `${group.indexes.length} row(s) written, ${read.length} read back`);
|
|
426
|
+
}
|
|
427
|
+
group.indexes.forEach((indexArg, positionArg) => {
|
|
428
|
+
written[indexArg] = read[positionArg];
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
return written;
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* The bookings of rows as a Buchungsstapel file states them (`rowsAsWritten`): what a file handed over, read back
|
|
436
|
+
* with `readExtfBuchungsstapel`, is compared with. `bookingsOfRows` of the rows before writing keeps what the file
|
|
437
|
+
* does not (a Belegfeld 1 the writer changes: cut to 36 characters before skr 7.3.0, mapped since where DATEV does
|
|
438
|
+
* not take it; a character Windows-1252 cannot hold), and Belegfeld 1 is compared, so such a booking would differ
|
|
439
|
+
* from the file forever.
|
|
440
|
+
*/
|
|
441
|
+
export const bookingsAsWritten = (rowsArg: readonly IDatevBuchungsstapelRow[]): IExportBooking[] => bookingsOfRows(rowsAsWritten(rowsArg));
|
|
442
|
+
|
|
297
443
|
/** Writes a Buchungsstapel: the rows of the drafts, the header and the caption row, encoded in Windows-1252. */
|
|
298
444
|
export const writeBuchungsstapel = (optionsArg: IBuchungsstapelOptions): IBuchungsstapelFile =>
|
|
299
445
|
fileOfRows(datevRowsOf(optionsArg.drafts, optionsArg.policy), optionsArg.header, optionsArg.filename);
|
|
@@ -345,15 +491,18 @@ const refuseCostCentresUnknown = (handedOverArg: readonly IExportBooking[]): voi
|
|
|
345
491
|
* handed over that the current ones no longer hold (`reversed`, each once for each time it is missing), the ones they
|
|
346
492
|
* still hold (`kept`, as they were handed over) and the current rows the bookings handed over do not hold (`added`),
|
|
347
493
|
* each in its order. A booking that stands in both is kept: a changed text or document link is no changed booking,
|
|
348
|
-
* a changed cost centre is.
|
|
349
|
-
*
|
|
494
|
+
* a changed cost centre is. The current rows are compared as a file states them (`bookingsAsWritten`), as the
|
|
495
|
+
* bookings handed over are; `added` are the rows themselves, which the writer writes. A booking handed over whose
|
|
496
|
+
* cost centres its record does not state (stored before 4.1) is refused (`handed_over_cost_centres_unknown`): pass
|
|
497
|
+
* `bookingsOfRows` of the rows sent instead.
|
|
350
498
|
*/
|
|
351
499
|
export const correctionOf = (
|
|
352
500
|
handedOverArg: readonly IExportBooking[],
|
|
353
501
|
currentArg: readonly IDatevBuchungsstapelRow[],
|
|
354
502
|
): { reversed: IExportBooking[]; kept: IExportBooking[]; added: IDatevBuchungsstapelRow[] } => {
|
|
355
503
|
refuseCostCentresUnknown(handedOverArg);
|
|
356
|
-
|
|
504
|
+
// the current rows as a file states them, as the state handed over was: a reference the writer changes is the same
|
|
505
|
+
const { leftPaired, rightPaired } = pairBookings(comparableOf(handedOverArg), bookingsAsWritten(currentArg));
|
|
357
506
|
return {
|
|
358
507
|
reversed: handedOverArg.filter((_bookingArg, indexArg) => !leftPaired[indexArg]),
|
|
359
508
|
kept: handedOverArg.filter((_bookingArg, indexArg) => leftPaired[indexArg]),
|
|
@@ -371,14 +520,16 @@ export interface ICorrectionBuchungsstapelOptions {
|
|
|
371
520
|
* The bookings of the period as they were handed over, as a whole: the bookings of its Buchungsstapel as stored
|
|
372
521
|
* (`IBuchungsstapelFile.bookings`), or after a correction the period's bookings as that correction left them
|
|
373
522
|
* (`bookingsAfter`). Each must state its cost centres: one stored before 4.1 does not, and is refused
|
|
374
|
-
* (`handed_over_cost_centres_unknown`); pass the rows sent for it.
|
|
523
|
+
* (`handed_over_cost_centres_unknown`); pass the rows sent for it. Bookings stored by any version, before or after
|
|
524
|
+
* writing, are compared as a file states them (`comparableOf`), so a reference the writer changed is no change.
|
|
375
525
|
*/
|
|
376
526
|
handedOver?: readonly IExportBooking[];
|
|
377
527
|
/**
|
|
378
528
|
* The rows of the Buchungsstapel as it was sent: the transmitted file read back (`@fin.cx/skr`
|
|
379
|
-
* `readExtfBuchungsstapel(bytes).rows`, skr
|
|
380
|
-
*
|
|
381
|
-
* bookings were stored
|
|
529
|
+
* `readExtfBuchungsstapel(bytes).rows`, skr 7.0.1 and later) or the rows given to the writer
|
|
530
|
+
* (`IBuchungsstapelFile.rows`), taken as the file states them (`bookingsAsWritten`). What DATEV received, cost
|
|
531
|
+
* centres (fields 37 and 38) included, so a reversal mirrors it exactly. For a Stapel whose bookings were stored
|
|
532
|
+
* before 4.1, which record no cost centres.
|
|
382
533
|
*/
|
|
383
534
|
handedOverRows?: readonly IDatevBuchungsstapelRow[];
|
|
384
535
|
/** the period's drafts as they stand now */
|
|
@@ -413,7 +564,8 @@ export interface ICorrectionBuchungsstapelFile extends IBuchungsstapelFile {
|
|
|
413
564
|
* twice or not at all; `handed_over_cost_centres_unknown` for a booking whose cost centres are not known.
|
|
414
565
|
*/
|
|
415
566
|
export const writeCorrectionBuchungsstapel = (optionsArg: ICorrectionBuchungsstapelOptions): ICorrectionBuchungsstapelFile => {
|
|
416
|
-
|
|
567
|
+
// rows read back from the file sent are as written already; rows given to the writer become what it wrote
|
|
568
|
+
const handedOver = optionsArg.handedOverRows !== undefined ? bookingsAsWritten(optionsArg.handedOverRows) : optionsArg.handedOver;
|
|
417
569
|
if (handedOver === undefined || (optionsArg.handedOver !== undefined && optionsArg.handedOverRows !== undefined)) {
|
|
418
570
|
throw new CompatibilityError('invalid_bookings', 'pass the state handed over once: the bookings stored (handedOver) or the rows sent (handedOverRows)');
|
|
419
571
|
}
|
|
@@ -427,5 +579,7 @@ export const writeCorrectionBuchungsstapel = (optionsArg: ICorrectionBuchungssta
|
|
|
427
579
|
throw new CompatibilityError('nothing_to_correct', 'the bookings of the period are the ones handed over; there is nothing to correct');
|
|
428
580
|
}
|
|
429
581
|
const rows = [...reversed.map((bookingArg) => ({ ...rowOfBooking(bookingArg), generalumkehr: true })), ...added];
|
|
430
|
-
|
|
582
|
+
const file = fileOfRows(rows, optionsArg.header, optionsArg.filename);
|
|
583
|
+
// the rows booked anew as the correction file states them, after the reversals
|
|
584
|
+
return { ...file, reversed, added, bookingsAfter: [...kept, ...file.bookings.slice(reversed.length)] };
|
|
431
585
|
};
|