@fin.cx/compatibility 5.0.1 → 5.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.
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/buchungsliste/index.d.ts +80 -0
- package/dist_ts/buchungsliste/index.js +385 -0
- package/dist_ts/buchungsliste/plugins.d.ts +2 -0
- package/dist_ts/buchungsliste/plugins.js +3 -0
- package/dist_ts/encoding/index.d.ts +8 -0
- package/dist_ts/encoding/index.js +16 -1
- package/dist_ts/error.d.ts +25 -7
- package/dist_ts/error.js +3 -2
- package/dist_ts/extf/index.d.ts +20 -3
- package/dist_ts/extf/index.js +68 -1
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/package.json +12 -7
- package/readme.md +58 -2
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/buchungsliste/index.ts +499 -0
- package/ts/buchungsliste/plugins.ts +3 -0
- package/ts/encoding/index.ts +17 -0
- package/ts/error.ts +34 -7
- package/ts/extf/index.ts +71 -3
- package/ts/index.ts +1 -0
package/ts/extf/index.ts
CHANGED
|
@@ -518,8 +518,9 @@ export const correctionOf = (
|
|
|
518
518
|
export interface ICorrectionBuchungsstapelOptions {
|
|
519
519
|
/**
|
|
520
520
|
* The bookings of the period as they were handed over, as a whole: the bookings of its Buchungsstapel as stored
|
|
521
|
-
* (`IBuchungsstapelFile.bookings`),
|
|
522
|
-
* (`bookingsAfter`)
|
|
521
|
+
* (`IBuchungsstapelFile.bookings`), after a correction the period's bookings as that correction left them
|
|
522
|
+
* (`bookingsAfter`), and after more than one Stapel the bookings that stand after all of them (`bookingsHeldOf`).
|
|
523
|
+
* Each must state its cost centres: one stored before 4.1 does not, and is refused
|
|
523
524
|
* (`handed_over_cost_centres_unknown`); pass the rows sent for it. Bookings stored by any version, before or after
|
|
524
525
|
* writing, are compared as a file states them (`comparableOf`), so a reference the writer changed is no change.
|
|
525
526
|
*/
|
|
@@ -529,7 +530,8 @@ export interface ICorrectionBuchungsstapelOptions {
|
|
|
529
530
|
* `readExtfBuchungsstapel(bytes).rows`, skr 7.0.1 and later) or the rows given to the writer
|
|
530
531
|
* (`IBuchungsstapelFile.rows`), taken as the file states them (`bookingsAsWritten`). What DATEV received, cost
|
|
531
532
|
* 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.
|
|
533
|
+
* before 4.1, which record no cost centres. The rows of one Stapel: after more than one, pass `handedOver` as
|
|
534
|
+
* `bookingsHeldOf` of the bookings of each file read back.
|
|
533
535
|
*/
|
|
534
536
|
handedOverRows?: readonly IDatevBuchungsstapelRow[];
|
|
535
537
|
/** the period's drafts as they stand now */
|
|
@@ -583,3 +585,69 @@ export const writeCorrectionBuchungsstapel = (optionsArg: ICorrectionBuchungssta
|
|
|
583
585
|
// the rows booked anew as the correction file states them, after the reversals
|
|
584
586
|
return { ...file, reversed, added, bookingsAfter: [...kept, ...file.bookings.slice(reversed.length)] };
|
|
585
587
|
};
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* The bookings of a period as DATEV holds them after its Stapel, handed over in the order given: the period's
|
|
591
|
+
* Buchungsstapel, the additional Stapel after it and its correction Stapel (`writeCorrectionBuchungsstapel`), each as
|
|
592
|
+
* the bookings it stated (`IBuchungsstapelFile.bookings` as stored, or `bookingsOfRows` of its file read back), in
|
|
593
|
+
* their order. An ordinary booking stands. A general reversal (field 118 "Generalumkehr") takes back one booking that
|
|
594
|
+
* stands before it, in an earlier Stapel or earlier in its own, and does not stand itself: the booking it mirrors says
|
|
595
|
+
* what it says (`differingBookingCount`'s fields, the reversal apart), compared as a file states them
|
|
596
|
+
* (`comparableOf`), so wording and document link do not count. A booking on the cost centres the reversal states is
|
|
597
|
+
* taken first, then one stored before 4.1, which records none; of several, the last, as a correction reverses the
|
|
598
|
+
* last of several bookings it no longer holds. A reversal of no booking that stands before it is refused
|
|
599
|
+
* (`invalid_bookings`, naming its Stapel and place): DATEV would hold a counter-booking of nothing. The bookings that
|
|
600
|
+
* stand, as they were given and in their order: what the next correction is compared against (`handedOver`), and
|
|
601
|
+
* after one correction its `bookingsAfter`. A booking a Buchungsstapel cannot hold is refused (`invalid_bookings`).
|
|
602
|
+
*/
|
|
603
|
+
export const bookingsHeldOf = (stapelArg: readonly (readonly IExportBooking[])[]): IExportBooking[] => {
|
|
604
|
+
const given = stapelArg.flat();
|
|
605
|
+
const comparable = comparableOf(given);
|
|
606
|
+
// where each booking stands: its Stapel and its place in it, for a refusal
|
|
607
|
+
const places = stapelArg.flatMap((stapelBookingsArg, stapelIndexArg) => stapelBookingsArg.map((_bookingArg, indexArg) => ({ stapel: stapelIndexArg, index: indexArg })));
|
|
608
|
+
const takenBack = given.map(() => false);
|
|
609
|
+
// the bookings that stand, by what they say: recorded ones on every key field and on the rest, unrecorded ones on the rest
|
|
610
|
+
const recordedByFullKey = new Map<string, number[]>();
|
|
611
|
+
const recordedByBaseKey = new Map<string, number[]>();
|
|
612
|
+
const unrecordedByBaseKey = new Map<string, number[]>();
|
|
613
|
+
const stand = (queuesArg: Map<string, number[]>, keyArg: string, indexArg: number): void => {
|
|
614
|
+
const queue = queuesArg.get(keyArg);
|
|
615
|
+
if (queue) {
|
|
616
|
+
queue.push(indexArg);
|
|
617
|
+
} else {
|
|
618
|
+
queuesArg.set(keyArg, [indexArg]);
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
// the last booking of a queue that still stands; a booking taken back through another queue is passed over for good
|
|
622
|
+
const lastStanding = (queuesArg: Map<string, number[]>, keyArg: string): number | undefined => {
|
|
623
|
+
const queue = queuesArg.get(keyArg);
|
|
624
|
+
while (queue && queue.length > 0 && takenBack[queue[queue.length - 1]]) {
|
|
625
|
+
queue.pop();
|
|
626
|
+
}
|
|
627
|
+
return queue?.[queue.length - 1];
|
|
628
|
+
};
|
|
629
|
+
comparable.forEach((bookingArg, indexArg) => {
|
|
630
|
+
if (!bookingArg.generalumkehr) {
|
|
631
|
+
if (recordsCostCentres(bookingArg)) {
|
|
632
|
+
stand(recordedByFullKey, fullKeyOf(bookingArg), indexArg);
|
|
633
|
+
stand(recordedByBaseKey, baseKeyOf(bookingArg), indexArg);
|
|
634
|
+
} else {
|
|
635
|
+
stand(unrecordedByBaseKey, baseKeyOf(bookingArg), indexArg);
|
|
636
|
+
}
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
// the booking the reversal mirrors says what it says
|
|
640
|
+
const { generalumkehr: _generalumkehr, ...mirrored } = bookingArg;
|
|
641
|
+
const baseKey = baseKeyOf(mirrored);
|
|
642
|
+
const unrecorded = lastStanding(unrecordedByBaseKey, baseKey);
|
|
643
|
+
const taken = recordsCostCentres(mirrored)
|
|
644
|
+
? lastStanding(recordedByFullKey, fullKeyOf(mirrored)) ?? unrecorded
|
|
645
|
+
: Math.max(lastStanding(recordedByBaseKey, baseKey) ?? -1, unrecorded ?? -1);
|
|
646
|
+
if (taken === undefined || taken < 0) {
|
|
647
|
+
const { stapel, index } = places[indexArg];
|
|
648
|
+
throw new CompatibilityError('invalid_bookings', `Stapel ${stapel + 1}, ${bookingNameOf(given[indexArg], index)} is a general reversal of no booking handed over before it`);
|
|
649
|
+
}
|
|
650
|
+
takenBack[taken] = true;
|
|
651
|
+
});
|
|
652
|
+
return given.filter((_bookingArg, indexArg) => !comparable[indexArg].generalumkehr && !takenBack[indexArg]);
|
|
653
|
+
};
|
package/ts/index.ts
CHANGED