@fin.cx/compatibility 5.2.1 → 5.3.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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@fin.cx/compatibility',
6
- version: '5.2.1',
6
+ version: '5.3.0',
7
7
  description: 'Exchange formats of third-party accounting systems: the EXTF Buchungsstapel in Windows-1252 on the rows of @fin.cx/skr, the document-image archive (document.xml and ZIP), and a payroll program\'s Buchungsliste read into journal drafts'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDRPQUE0TztDQUMxUCxDQUFBIn0=
@@ -1,5 +1,5 @@
1
1
  import * as plugins from './plugins.js';
2
- export { CompatibilityError, type TCompatibilityErrorCode, type ICompatibilityErrorDetails } from '../error.js';
2
+ export { CompatibilityError, type TCompatibilityErrorCode, type ICompatibilityErrorDetails, type TBuchungslisteRefusalReason, } from '../error.js';
3
3
  export type IDatevBuchungsstapelRow = plugins.skrCore.IDatevBuchungsstapelRow;
4
4
  /** One row of a Buchungsliste as the file states it: one booking of the amount from the Sollkonto to the Habenkonto. */
5
5
  export interface IBuchungslisteRow {
@@ -1,7 +1,7 @@
1
1
  import * as plugins from './plugins.js';
2
2
  import { CompatibilityError } from '../error.js';
3
3
  import { decodeWindows1252 } from '../encoding/index.js';
4
- export { CompatibilityError } from '../error.js';
4
+ export { CompatibilityError, } from '../error.js';
5
5
  /** How a field is named in a refusal when the file names no column of it. */
6
6
  const FIELD_NAMES = {
7
7
  belegdatum: 'Belegdatum',
@@ -63,8 +63,8 @@ const columnKeyOf = (nameArg) => nameArg
63
63
  .replace(/ü/gu, 'ue')
64
64
  .replace(/ß/gu, 'ss')
65
65
  .replace(/[^a-z0-9%]/gu, '');
66
- /** A Buchungsliste that cannot be read as it is. */
67
- const refusal = (messageArg, detailsArg) => new CompatibilityError('invalid_buchungsliste', messageArg, detailsArg);
66
+ /** A Buchungsliste that cannot be read as it is, and why. */
67
+ const refusal = (reasonArg, messageArg, detailsArg) => new CompatibilityError('invalid_buchungsliste', messageArg, { reason: reasonArg, ...detailsArg });
68
68
  /**
69
69
  * The delimiter the first line separates its names by: the first of semicolon, tab and comma that stands in it outside
70
70
  * double quotes (unconfirmed which one lohn+gehalt writes). Refuses a first line that has none: a single name cannot
@@ -83,7 +83,7 @@ const delimiterOf = (firstLineArg, lineArg) => {
83
83
  }
84
84
  const delimiter = DELIMITERS.find((delimiterArg) => outside.has(delimiterArg));
85
85
  if (delimiter === undefined) {
86
- throw refusal(`line ${lineArg}: the field names of the first line are separated by none of semicolon, tab and comma`, { line: lineArg });
86
+ throw refusal('unreadable', `line ${lineArg}: the field names of the first line are separated by none of semicolon, tab and comma`, { line: lineArg });
87
87
  }
88
88
  return delimiter;
89
89
  };
@@ -136,7 +136,7 @@ const recordsOf = (textArg, delimiterArg) => {
136
136
  }
137
137
  }
138
138
  else if (closed) {
139
- throw refusal(`line ${line}: field ${fields.length + 1} has text after its closing quote`, { line });
139
+ throw refusal('unreadable', `line ${line}: field ${fields.length + 1} has text after its closing quote`, { line });
140
140
  }
141
141
  else if (char === '"' && current === '') {
142
142
  quoted = true;
@@ -146,7 +146,7 @@ const recordsOf = (textArg, delimiterArg) => {
146
146
  }
147
147
  }
148
148
  if (quoted) {
149
- throw refusal(`line ${recordLine}: field ${fields.length + 1} opens a quote that is never closed`, { line: recordLine });
149
+ throw refusal('unreadable', `line ${recordLine}: field ${fields.length + 1} opens a quote that is never closed`, { line: recordLine });
150
150
  }
151
151
  // the last record, where the text does not end in a line break
152
152
  if (current !== '' || closed || fields.length > 0) {
@@ -196,19 +196,19 @@ const centsOf = (valueArg) => {
196
196
  */
197
197
  export const readBuchungsliste = (bytesArg) => {
198
198
  if (bytesArg[0] === 0xef && bytesArg[1] === 0xbb && bytesArg[2] === 0xbf) {
199
- throw refusal('the Buchungsliste begins with the byte order mark of UTF-8; it is read as Windows-1252 (ANSI)', { line: 1 });
199
+ throw refusal('unreadable', 'the Buchungsliste begins with the byte order mark of UTF-8; it is read as Windows-1252 (ANSI)', { line: 1 });
200
200
  }
201
201
  const text = decodeWindows1252(bytesArg);
202
202
  const lines = text.split(/\r\n|\n|\r/u);
203
203
  // the first line that states anything names the fields
204
204
  const firstLineIndex = lines.findIndex((lineArg) => /[^\s;,"]/u.test(lineArg));
205
205
  if (firstLineIndex < 0) {
206
- throw refusal('the Buchungsliste has no first line naming its fields', {});
206
+ throw refusal('unreadable', 'the Buchungsliste has no first line naming its fields', {});
207
207
  }
208
208
  const delimiter = delimiterOf(lines[firstLineIndex], firstLineIndex + 1);
209
209
  const [captionRecord, ...dataRecords] = recordsOf(text, delimiter).filter((recordArg) => !isBlank(recordArg));
210
210
  if (captionRecord === undefined) {
211
- throw refusal('the Buchungsliste has no first line naming its fields', {});
211
+ throw refusal('unreadable', 'the Buchungsliste has no first line naming its fields', {});
212
212
  }
213
213
  const captions = captionRecord.fields.map((fieldArg) => fieldArg.trim());
214
214
  // the column of each field the first line names
@@ -224,13 +224,13 @@ export const readBuchungsliste = (bytesArg) => {
224
224
  }
225
225
  const earlier = columnOf.get(field);
226
226
  if (earlier !== undefined) {
227
- throw refusal(`line ${captionRecord.line}: columns ${earlier + 1} "${captions[earlier]}" and ${columnArg + 1} "${captionArg}" both state the ${FIELD_NAMES[field]}`, { line: captionRecord.line, field: captionArg });
227
+ throw refusal('unreadable', `line ${captionRecord.line}: columns ${earlier + 1} "${captions[earlier]}" and ${columnArg + 1} "${captionArg}" both state the ${FIELD_NAMES[field]}`, { line: captionRecord.line, field: captionArg });
228
228
  }
229
229
  columnOf.set(field, columnArg);
230
230
  });
231
231
  const missing = REQUIRED_FIELDS.filter((fieldArg) => !columnOf.has(fieldArg));
232
232
  if (missing.length > 0) {
233
- throw refusal(`line ${captionRecord.line}: the Buchungsliste has no column ${missing.map((fieldArg) => FIELD_NAMES[fieldArg]).join(', ')}`, {
233
+ throw refusal('unreadable', `line ${captionRecord.line}: the Buchungsliste has no column ${missing.map((fieldArg) => FIELD_NAMES[fieldArg]).join(', ')}`, {
234
234
  line: captionRecord.line,
235
235
  field: FIELD_NAMES[missing[0]],
236
236
  });
@@ -244,13 +244,13 @@ export const readBuchungsliste = (bytesArg) => {
244
244
  const row = indexArg + 1;
245
245
  const { line } = recordArg;
246
246
  if (recordArg.fields.length !== captions.length) {
247
- throw refusal(`row ${row} (line ${line}) has ${recordArg.fields.length} fields, not the ${captions.length} of the first line`, { row, line });
247
+ throw refusal('unreadable', `row ${row} (line ${line}) has ${recordArg.fields.length} fields, not the ${captions.length} of the first line`, { row, line });
248
248
  }
249
249
  const at = (fieldArg) => {
250
250
  const column = columnOf.get(fieldArg);
251
251
  return column === undefined ? '' : recordArg.fields[column].trim();
252
252
  };
253
- const malformed = (fieldArg, messageArg) => refusal(`row ${row} (line ${line}): ${messageArg}`, { row, line, field: nameOf(fieldArg), value: at(fieldArg) });
253
+ const malformed = (fieldArg, messageArg, reasonArg = 'field_malformed') => refusal(reasonArg, `row ${row} (line ${line}): ${messageArg}`, { row, line, field: nameOf(fieldArg), value: at(fieldArg) });
254
254
  const day = (fieldArg) => {
255
255
  if (at(fieldArg) === '')
256
256
  return undefined;
@@ -266,12 +266,12 @@ export const readBuchungsliste = (bytesArg) => {
266
266
  };
267
267
  for (const field of UNMAPPED_FIELDS) {
268
268
  if (at(field) !== '') {
269
- throw malformed(field, `the row states ${nameOf(field)} "${at(field)}"; this version maps no Zusatzangaben (§ 13b), EU Land or EU %`);
269
+ throw malformed(field, `the row states ${nameOf(field)} "${at(field)}"; this version maps no Zusatzangaben (§ 13b), EU Land or EU %`, 'field_unmapped');
270
270
  }
271
271
  }
272
272
  const currency = at('waehrung');
273
273
  if (currency !== '' && currency !== 'EUR') {
274
- throw malformed('waehrung', `the row is in ${currency}; these books are in euro`);
274
+ throw malformed('waehrung', `the row is in ${currency}; these books are in euro`, 'currency_unsupported');
275
275
  }
276
276
  const belegDatum = day('belegdatum');
277
277
  if (!belegDatum)
@@ -291,7 +291,7 @@ export const readBuchungsliste = (bytesArg) => {
291
291
  const habenkonto = account('habenkonto');
292
292
  const key = at('steuerschluessel');
293
293
  if (!plugins.skrCore.isKnownBuKey(key)) {
294
- throw malformed('steuerschluessel', `the ${nameOf('steuerschluessel')} "${key}" is no DATEV key these books know (${Object.keys(plugins.skrCore.BU_KEY_RULES).join(', ')})`);
294
+ throw malformed('steuerschluessel', `the ${nameOf('steuerschluessel')} "${key}" is no DATEV key these books know (${Object.keys(plugins.skrCore.BU_KEY_RULES).join(', ')})`, 'bu_key_unknown');
295
295
  }
296
296
  const texts = {
297
297
  ...(at('belegnummernkreis') !== '' ? { belegnummernkreis: at('belegnummernkreis') } : {}),
@@ -370,16 +370,18 @@ export const importBuchungsliste = (bytesArg, policyArg) => {
370
370
  }
371
371
  catch (error) {
372
372
  if (error instanceof plugins.skrCore.DatevImportError) {
373
- throw refusal(`row ${row} (line ${line}): ${error.message}`, { row, line });
373
+ // skr refuses a row's draft for a tax whose account cannot be told; any other refusal of its is a row that gives no entry
374
+ const reason = error.code === 'extf_tax_account_unclear' ? 'tax_account_unclear' : 'row_invalid';
375
+ throw refusal(reason, `row ${row} (line ${line}): ${error.message}`, { row, line });
374
376
  }
375
377
  throw error;
376
378
  }
377
379
  const validation = plugins.skrCore.validateJournalDraft(draft, policyArg);
378
380
  if (!validation.valid) {
379
- throw refusal(`row ${row} (line ${line}) gives no valid entry: ${validation.errors.join('; ')}`, { row, line, errors: validation.errors });
381
+ throw refusal('row_invalid', `row ${row} (line ${line}) gives no valid entry: ${validation.errors.join('; ')}`, { row, line, errors: validation.errors });
380
382
  }
381
383
  return { row, buchungslisteRow, datevRow, draft };
382
384
  });
383
385
  return { entries, warnings };
384
386
  };
385
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9idWNodW5nc2xpc3RlL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBbUMsTUFBTSxhQUFhLENBQUM7QUFDbEYsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFekQsT0FBTyxFQUFFLGtCQUFrQixFQUFpRSxNQUFNLGFBQWEsQ0FBQztBQStDaEgsNkVBQTZFO0FBQzdFLE1BQU0sV0FBVyxHQUFrRDtJQUNqRSxVQUFVLEVBQUUsWUFBWTtJQUN4QixhQUFhLEVBQUUsZUFBZTtJQUM5QixlQUFlLEVBQUUsaUJBQWlCO0lBQ2xDLGlCQUFpQixFQUFFLG1CQUFtQjtJQUN0QyxXQUFXLEVBQUUsYUFBYTtJQUMxQixZQUFZLEVBQUUsY0FBYztJQUM1QixjQUFjLEVBQUUsZ0JBQWdCO0lBQ2hDLFFBQVEsRUFBRSxTQUFTO0lBQ25CLFNBQVMsRUFBRSxXQUFXO0lBQ3RCLFVBQVUsRUFBRSxZQUFZO0lBQ3hCLGdCQUFnQixFQUFFLGlCQUFpQjtJQUNuQyxZQUFZLEVBQUUsY0FBYztJQUM1QixhQUFhLEVBQUUsY0FBYztJQUM3QixhQUFhLEVBQUUsZUFBZTtJQUM5QixNQUFNLEVBQUUsU0FBUztJQUNqQixTQUFTLEVBQUUsTUFBTTtDQUNsQixDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sZUFBZSxHQUE2QyxJQUFJLEdBQUcsQ0FBOEI7SUFDckcsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDO0lBQzVCLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQztJQUNsQyxDQUFDLGlCQUFpQixFQUFFLGlCQUFpQixDQUFDO0lBQ3RDLENBQUMsbUJBQW1CLEVBQUUsbUJBQW1CLENBQUM7SUFDMUMsQ0FBQyxhQUFhLEVBQUUsYUFBYSxDQUFDO0lBQzlCLENBQUMsY0FBYyxFQUFFLGNBQWMsQ0FBQztJQUNoQyxDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixDQUFDO0lBQ3BDLENBQUMsVUFBVSxFQUFFLFVBQVUsQ0FBQztJQUN4QixDQUFDLFdBQVcsRUFBRSxXQUFXLENBQUM7SUFDMUIsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDO0lBQzVCLENBQUMsa0JBQWtCLEVBQUUsa0JBQWtCLENBQUM7SUFDeEMsQ0FBQyxjQUFjLEVBQUUsY0FBYyxDQUFDO0lBQ2hDLENBQUMsZUFBZSxFQUFFLGNBQWMsQ0FBQztJQUNqQyxDQUFDLGVBQWUsRUFBRSxlQUFlLENBQUM7SUFDbEMsQ0FBQyxlQUFlLEVBQUUsZUFBZSxDQUFDO0lBQ2xDLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQztJQUNsQyxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUM7SUFDcEIsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDO0NBQ3JCLENBQUMsQ0FBQztBQUVILGlEQUFpRDtBQUNqRCxNQUFNLGVBQWUsR0FBbUMsQ0FBQyxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBRXBILG1KQUFtSjtBQUNuSixNQUFNLGVBQWUsR0FBbUMsQ0FBQyxlQUFlLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0FBRWpHLDhIQUE4SDtBQUM5SCxNQUFNLFVBQVUsR0FBc0IsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBRXZEOzs7R0FHRztBQUNILE1BQU0sV0FBVyxHQUFHLENBQUMsT0FBZSxFQUFVLEVBQUUsQ0FDOUMsT0FBTztLQUNKLFdBQVcsRUFBRTtLQUNiLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDO0tBQ3BCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDO0tBQ3BCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDO0tBQ3BCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDO0tBQ3BCLE9BQU8sQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUM7QUEyQ2pDLG9EQUFvRDtBQUNwRCxNQUFNLE9BQU8sR0FBRyxDQUFDLFVBQWtCLEVBQUUsVUFBc0MsRUFBc0IsRUFBRSxDQUNqRyxJQUFJLGtCQUFrQixDQUFDLHVCQUF1QixFQUFFLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztBQUUxRTs7OztHQUlHO0FBQ0gsTUFBTSxXQUFXLEdBQUcsQ0FBQyxZQUFvQixFQUFFLE9BQWUsRUFBVSxFQUFFO0lBQ3BFLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDbEMsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ25CLEtBQUssTUFBTSxJQUFJLElBQUksWUFBWSxFQUFFLENBQUM7UUFDaEMsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDakIsTUFBTSxHQUFHLENBQUMsTUFBTSxDQUFDO1FBQ25CLENBQUM7YUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbkIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQixDQUFDO0lBQ0gsQ0FBQztJQUNELE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUMvRSxJQUFJLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUM1QixNQUFNLE9BQU8sQ0FBQyxRQUFRLE9BQU8sdUZBQXVGLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUMzSSxDQUFDO0lBQ0QsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQyxDQUFDO0FBRUY7Ozs7O0dBS0c7QUFDSCxNQUFNLFNBQVMsR0FBRyxDQUFDLE9BQWUsRUFBRSxZQUFvQixFQUFhLEVBQUU7SUFDckUsTUFBTSxPQUFPLEdBQWMsRUFBRSxDQUFDO0lBQzlCLElBQUksTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUMxQixJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUM7SUFDakIsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ25CLElBQUksTUFBTSxHQUFHLEtBQUssQ0FBQztJQUNuQixJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7SUFDYixJQUFJLFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDbkIsTUFBTSxRQUFRLEdBQUcsR0FBUyxFQUFFO1FBQzFCLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDckIsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDakIsQ0FBQyxDQUFDO0lBQ0YsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsS0FBSyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3ZELE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QixNQUFNLFNBQVMsR0FBRyxJQUFJLEtBQUssSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLElBQUksSUFBSSxPQUFPLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDO1FBQ2xGLElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksT0FBTyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztnQkFDL0MsT0FBTyxJQUFJLEdBQUcsQ0FBQztnQkFDZixLQUFLLElBQUksQ0FBQyxDQUFDO1lBQ2IsQ0FBQztpQkFBTSxJQUFJLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztnQkFDeEIsTUFBTSxHQUFHLEtBQUssQ0FBQztnQkFDZixNQUFNLEdBQUcsSUFBSSxDQUFDO1lBQ2hCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixPQUFPLElBQUksSUFBSSxDQUFDO2dCQUNoQixJQUFJLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1QixDQUFDO1FBQ0gsQ0FBQzthQUFNLElBQUksSUFBSSxLQUFLLFlBQVksRUFBRSxDQUFDO1lBQ2pDLFFBQVEsRUFBRSxDQUFDO1FBQ2IsQ0FBQzthQUFNLElBQUksSUFBSSxLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDMUMsSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDZCxRQUFRLEVBQUUsQ0FBQztnQkFDWCxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO2dCQUMzQyxNQUFNLEdBQUcsRUFBRSxDQUFDO2dCQUNaLElBQUksSUFBSSxDQUFDLENBQUM7Z0JBQ1YsVUFBVSxHQUFHLElBQUksQ0FBQztZQUNwQixDQUFDO1FBQ0gsQ0FBQzthQUFNLElBQUksTUFBTSxFQUFFLENBQUM7WUFDbEIsTUFBTSxPQUFPLENBQUMsUUFBUSxJQUFJLFdBQVcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLG1DQUFtQyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN2RyxDQUFDO2FBQU0sSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLE9BQU8sS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUMxQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ2hCLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxJQUFJLElBQUksQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQztJQUNELElBQUksTUFBTSxFQUFFLENBQUM7UUFDWCxNQUFNLE9BQU8sQ0FBQyxRQUFRLFVBQVUsV0FBVyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMscUNBQXFDLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUMzSCxDQUFDO0lBQ0QsK0RBQStEO0lBQy9ELElBQUksT0FBTyxLQUFLLEVBQUUsSUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNsRCxRQUFRLEVBQUUsQ0FBQztRQUNYLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUNELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUMsQ0FBQztBQUVGLG1GQUFtRjtBQUNuRixNQUFNLE9BQU8sR0FBRyxDQUFDLFNBQWtCLEVBQVcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7QUFFOUcsMkRBQTJEO0FBQzNELE1BQU0sS0FBSyxHQUFHLENBQUMsUUFBZ0IsRUFBb0IsRUFBRTtJQUNuRCxNQUFNLEtBQUssR0FBRyw4QkFBOEIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDNUQsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUM3QixNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEYsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3RELE9BQU8sSUFBSSxDQUFDLGNBQWMsRUFBRSxLQUFLLElBQUksSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLEtBQUssS0FBSyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUM1SCxDQUFDLENBQUM7QUFFRjs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sR0FBRyxDQUFDLFFBQWdCLEVBQXNCLEVBQUU7SUFDdkQsTUFBTSxLQUFLLEdBQUcsaURBQWlELENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQy9FLElBQUksQ0FBQyxLQUFLO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDN0IsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDM0MsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLEVBQUU7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUN4QyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUUsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0FBQzNDLENBQUMsQ0FBQztBQUVGOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLFFBQW9CLEVBQWtCLEVBQUU7SUFDeEUsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ3pFLE1BQU0sT0FBTyxDQUFDLCtGQUErRixFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDOUgsQ0FBQztJQUNELE1BQU0sSUFBSSxHQUFHLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDeEMsdURBQXVEO0lBQ3ZELE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMvRSxJQUFJLGNBQWMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN2QixNQUFNLE9BQU8sQ0FBQyx1REFBdUQsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBQ0QsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRSxjQUFjLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDekUsTUFBTSxDQUFDLGFBQWEsRUFBRSxHQUFHLFdBQVcsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQzlHLElBQUksYUFBYSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sT0FBTyxDQUFDLHVEQUF1RCxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzdFLENBQUM7SUFDRCxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFFekUsZ0RBQWdEO0lBQ2hELE1BQU0sUUFBUSxHQUFhLEVBQUUsQ0FBQztJQUM5QixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBK0IsQ0FBQztJQUN4RCxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsVUFBVSxFQUFFLFNBQVMsRUFBRSxFQUFFO1FBQ3pDLE1BQU0sS0FBSyxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7UUFDM0QsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDeEIsUUFBUSxDQUFDLElBQUksQ0FDWCxVQUFVLEtBQUssRUFBRTtnQkFDZixDQUFDLENBQUMsVUFBVSxTQUFTLEdBQUcsQ0FBQyx1Q0FBdUM7Z0JBQ2hFLENBQUMsQ0FBQyxVQUFVLFNBQVMsR0FBRyxDQUFDLEtBQUssVUFBVSw2RUFBNkUsQ0FDeEgsQ0FBQztZQUNGLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwQyxJQUFJLE9BQU8sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMxQixNQUFNLE9BQU8sQ0FDWCxRQUFRLGFBQWEsQ0FBQyxJQUFJLGFBQWEsT0FBTyxHQUFHLENBQUMsS0FBSyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsU0FBUyxHQUFHLENBQUMsS0FBSyxVQUFVLG9CQUFvQixXQUFXLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFDckosRUFBRSxJQUFJLEVBQUUsYUFBYSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLENBQ2hELENBQUM7UUFDSixDQUFDO1FBQ0QsUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDakMsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLE9BQU8sR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUM5RSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDdkIsTUFBTSxPQUFPLENBQUMsUUFBUSxhQUFhLENBQUMsSUFBSSxxQ0FBcUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDMUksSUFBSSxFQUFFLGFBQWEsQ0FBQyxJQUFJO1lBQ3hCLEtBQUssRUFBRSxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQy9CLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCx5REFBeUQ7SUFDekQsTUFBTSxNQUFNLEdBQUcsQ0FBQyxRQUE2QixFQUFVLEVBQUU7UUFDdkQsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN0QyxPQUFPLE1BQU0sS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3pFLENBQUMsQ0FBQztJQUVGLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsUUFBUSxFQUFxQixFQUFFO1FBQ3RFLE1BQU0sR0FBRyxHQUFHLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFDekIsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoRCxNQUFNLE9BQU8sQ0FBQyxPQUFPLEdBQUcsVUFBVSxJQUFJLFNBQVMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixRQUFRLENBQUMsTUFBTSxvQkFBb0IsRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2hKLENBQUM7UUFDRCxNQUFNLEVBQUUsR0FBRyxDQUFDLFFBQTZCLEVBQVUsRUFBRTtZQUNuRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3RDLE9BQU8sTUFBTSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3JFLENBQUMsQ0FBQztRQUNGLE1BQU0sU0FBUyxHQUFHLENBQUMsUUFBNkIsRUFBRSxVQUFrQixFQUFzQixFQUFFLENBQzFGLE9BQU8sQ0FBQyxPQUFPLEdBQUcsVUFBVSxJQUFJLE1BQU0sVUFBVSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbkgsTUFBTSxHQUFHLEdBQUcsQ0FBQyxRQUE2QixFQUFvQixFQUFFO1lBQzlELElBQUksRUFBRSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUU7Z0JBQUUsT0FBTyxTQUFTLENBQUM7WUFDMUMsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxLQUFLO2dCQUFFLE1BQU0sU0FBUyxDQUFDLFFBQVEsRUFBRSxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUMsUUFBUSxDQUFDLHdCQUF3QixDQUFDLENBQUM7WUFDeEcsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDLENBQUM7UUFDRixNQUFNLE9BQU8sR0FBRyxDQUFDLFFBQTZCLEVBQVUsRUFBRTtZQUN4RCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQUUsTUFBTSxTQUFTLENBQUMsUUFBUSxFQUFFLE9BQU8sTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMseUNBQXlDLENBQUMsQ0FBQztZQUNuSixPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN0QixDQUFDLENBQUM7UUFFRixLQUFLLE1BQU0sS0FBSyxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3BDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDO2dCQUNyQixNQUFNLFNBQVMsQ0FBQyxLQUFLLEVBQUUsa0JBQWtCLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUMsS0FBSyxDQUFDLGdFQUFnRSxDQUFDLENBQUM7WUFDeEksQ0FBQztRQUNILENBQUM7UUFDRCxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEMsSUFBSSxRQUFRLEtBQUssRUFBRSxJQUFJLFFBQVEsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMxQyxNQUFNLFNBQVMsQ0FBQyxVQUFVLEVBQUUsaUJBQWlCLFFBQVEsMkJBQTJCLENBQUMsQ0FBQztRQUNwRixDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxVQUFVO1lBQUUsTUFBTSxTQUFTLENBQUMsWUFBWSxFQUFFLHFCQUFxQixNQUFNLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzVGLE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUMzQyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUNyQyxJQUFJLE1BQU0sS0FBSyxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDaEQsTUFBTSxTQUFTLENBQUMsaUJBQWlCLEVBQUUsT0FBTyxNQUFNLENBQUMsaUJBQWlCLENBQUMsS0FBSyxNQUFNLGlDQUFpQyxDQUFDLENBQUM7UUFDbkgsQ0FBQztRQUNELE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO1FBQ2xELElBQUksV0FBVyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzlCLE1BQU0sU0FBUyxDQUNiLGdCQUFnQixFQUNoQixPQUFPLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyw2R0FBNkcsQ0FDdEssQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLFdBQVcsS0FBSyxDQUFDO1lBQUUsTUFBTSxTQUFTLENBQUMsZ0JBQWdCLEVBQUUsT0FBTyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLENBQUMsZ0JBQWdCLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUNwSSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdkMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3pDLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sU0FBUyxDQUNiLGtCQUFrQixFQUNsQixPQUFPLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEdBQUcsdUNBQXVDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FDeEksQ0FBQztRQUNKLENBQUM7UUFDRCxNQUFNLEtBQUssR0FBRztZQUNaLEdBQUcsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsaUJBQWlCLEVBQUUsRUFBRSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3pGLEdBQUcsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3ZFLEdBQUcsQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLFlBQVksRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLGFBQWEsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQzlFLENBQUM7UUFDRixPQUFPO1lBQ0wsR0FBRztZQUNILElBQUk7WUFDSixVQUFVO1lBQ1YsR0FBRyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzNDLEdBQUcsQ0FBQyxNQUFNLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLGVBQWUsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzdELFlBQVksRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDO1lBQ2hDLFdBQVc7WUFDWCxTQUFTO1lBQ1QsVUFBVTtZQUNWLGdCQUFnQixFQUFFLEdBQUc7WUFDckIsR0FBRyxLQUFLO1NBQ1QsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQztBQUM1QixDQUFDLENBQUM7QUFFRjs7Ozs7R0FLRztBQUNILE1BQU0sWUFBWSxHQUFHLENBQUMsTUFBeUIsRUFBc0IsRUFBRTtJQUNyRSxNQUFNLEVBQUUsaUJBQWlCLEVBQUUsV0FBVyxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBQ2xELElBQUksaUJBQWlCLEtBQUssU0FBUyxJQUFJLFdBQVcsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNqRSxPQUFPLFdBQVcsQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLGlCQUFpQixHQUFHLFdBQVcsRUFBRSxDQUFDO0lBQ3hHLENBQUM7SUFDRCxPQUFPLFdBQVcsSUFBSSxpQkFBaUIsQ0FBQztBQUMxQyxDQUFDLENBQUM7QUFFRjs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUcsQ0FBQyxNQUF5QixFQUEyQixFQUFFO0lBQy9GLE1BQU0sVUFBVSxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN4QyxPQUFPO1FBQ0wsV0FBVyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQztRQUN6QyxTQUFTLEVBQUUsTUFBTSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRztRQUM3QyxLQUFLLEVBQUUsTUFBTSxDQUFDLFNBQVM7UUFDdkIsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO1FBQzdCLFlBQVksRUFBRSxNQUFNLENBQUMsZ0JBQWdCO1FBQ3JDLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVTtRQUM3QixHQUFHLENBQUMsVUFBVSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ25ELFlBQVksRUFBRSxNQUFNLENBQUMsWUFBWTtRQUNqQyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzVFLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7S0FDL0UsQ0FBQztBQUNKLENBQUMsQ0FBQztBQVdGOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxDQUNqQyxRQUFvQixFQUNwQixTQUF5QyxFQUNxQixFQUFFO0lBQ2hFLE1BQU0sRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEdBQUcsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdkQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGdCQUFnQixFQUE2QixFQUFFO1FBQ3ZFLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsZ0JBQWdCLENBQUM7UUFDdkMsTUFBTSxRQUFRLEdBQUcsMEJBQTBCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUM5RCxJQUFJLEtBQW9DLENBQUM7UUFDekMsSUFBSSxDQUFDO1lBQ0gsS0FBSyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxLQUFLLFlBQVksT0FBTyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUN0RCxNQUFNLE9BQU8sQ0FBQyxPQUFPLEdBQUcsVUFBVSxJQUFJLE1BQU0sS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDOUUsQ0FBQztZQUNELE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztRQUNELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQzFFLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDdEIsTUFBTSxPQUFPLENBQUMsT0FBTyxHQUFHLFVBQVUsSUFBSSwyQkFBMkIsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzdJLENBQUM7UUFDRCxPQUFPLEVBQUUsR0FBRyxFQUFFLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUNwRCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLENBQUM7QUFDL0IsQ0FBQyxDQUFDIn0=
387
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9idWNodW5nc2xpc3RlL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBcUUsTUFBTSxhQUFhLENBQUM7QUFDcEgsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFekQsT0FBTyxFQUNMLGtCQUFrQixHQUluQixNQUFNLGFBQWEsQ0FBQztBQStDckIsNkVBQTZFO0FBQzdFLE1BQU0sV0FBVyxHQUFrRDtJQUNqRSxVQUFVLEVBQUUsWUFBWTtJQUN4QixhQUFhLEVBQUUsZUFBZTtJQUM5QixlQUFlLEVBQUUsaUJBQWlCO0lBQ2xDLGlCQUFpQixFQUFFLG1CQUFtQjtJQUN0QyxXQUFXLEVBQUUsYUFBYTtJQUMxQixZQUFZLEVBQUUsY0FBYztJQUM1QixjQUFjLEVBQUUsZ0JBQWdCO0lBQ2hDLFFBQVEsRUFBRSxTQUFTO0lBQ25CLFNBQVMsRUFBRSxXQUFXO0lBQ3RCLFVBQVUsRUFBRSxZQUFZO0lBQ3hCLGdCQUFnQixFQUFFLGlCQUFpQjtJQUNuQyxZQUFZLEVBQUUsY0FBYztJQUM1QixhQUFhLEVBQUUsY0FBYztJQUM3QixhQUFhLEVBQUUsZUFBZTtJQUM5QixNQUFNLEVBQUUsU0FBUztJQUNqQixTQUFTLEVBQUUsTUFBTTtDQUNsQixDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sZUFBZSxHQUE2QyxJQUFJLEdBQUcsQ0FBOEI7SUFDckcsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDO0lBQzVCLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQztJQUNsQyxDQUFDLGlCQUFpQixFQUFFLGlCQUFpQixDQUFDO0lBQ3RDLENBQUMsbUJBQW1CLEVBQUUsbUJBQW1CLENBQUM7SUFDMUMsQ0FBQyxhQUFhLEVBQUUsYUFBYSxDQUFDO0lBQzlCLENB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
@@ -14,11 +14,30 @@
14
14
  * centres its record does not state (stored before 4.1) and no rows sent were given; the message names it;
15
15
  * - `invalid_buchungsliste`: a Buchungsliste that cannot be read or booked as it is: no header line, a required
16
16
  * column missing, a field that is not of its format, a field this version does not map, or a row that gives no
17
- * valid entry; `details` names the line, the row and the field where it can.
17
+ * valid entry; `details` names why (`reason`), the line, the row and the field where it can.
18
18
  */
19
19
  export type TCompatibilityErrorCode = 'invalid_bookings' | 'invalid_header' | 'export_failed' | 'invalid_documents' | 'nothing_to_correct' | 'handed_over_cost_centres_unknown' | 'invalid_buchungsliste';
20
+ /**
21
+ * Why a Buchungsliste was refused (`invalid_buchungsliste`), so a consumer can tell its user without reading the
22
+ * message:
23
+ * - `unreadable`: the text is no list of rows of the first line's fields: a byte order mark of UTF-8, no first line,
24
+ * no delimiter, a quote never closed or text after a closing quote, a required column missing or two columns of
25
+ * one field, a row of another number of fields;
26
+ * - `field_malformed`: a field not of its format (a day, an amount or 0, an account, a Buchungsperiode), or no
27
+ * Belegdatum;
28
+ * - `field_unmapped`: a row that states Zusatzangaben, an EU Land or an EU %, which this version does not map;
29
+ * - `currency_unsupported`: a Währung other than EUR;
30
+ * - `bu_key_unknown`: a Steuerschlüssel `@fin.cx/skr` does not know;
31
+ * - `tax_account_unclear`: a row with a tax where the account it is computed on cannot be told (skr's
32
+ * `extf_tax_account_unclear`);
33
+ * - `row_invalid`: a row whose entry skr refuses otherwise; where its check (`validateJournalDraft`) refused it, what
34
+ * the check found in `details.errors`.
35
+ */
36
+ export type TBuchungslisteRefusalReason = 'unreadable' | 'field_malformed' | 'field_unmapped' | 'currency_unsupported' | 'bu_key_unknown' | 'tax_account_unclear' | 'row_invalid';
20
37
  /** Where a refusal of a file read stands, as far as it is known; empty for a file written. */
21
38
  export interface ICompatibilityErrorDetails {
39
+ /** why a Buchungsliste was refused; stated on every `invalid_buchungsliste` */
40
+ reason?: TBuchungslisteRefusalReason;
22
41
  /** the data row, from 1 */
23
42
  row?: number;
24
43
  /** the line of the file, from 1 */
package/dist_ts/error.js CHANGED
@@ -6,4 +6,4 @@ export class CompatibilityError extends Error {
6
6
  this.details = detailsArg;
7
7
  }
8
8
  }
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9lcnJvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUF5Q0EsTUFBTSxPQUFPLGtCQUFtQixTQUFRLEtBQUs7SUFJM0MsWUFBWSxPQUFnQyxFQUFFLFVBQWtCLEVBQUUsYUFBeUMsRUFBRTtRQUMzRyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEIsSUFBSSxDQUFDLElBQUksR0FBRyxvQkFBb0IsQ0FBQztRQUNqQyxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztRQUNwQixJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQztJQUM1QixDQUFDO0NBQ0YifQ==
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9lcnJvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFvRUEsTUFBTSxPQUFPLGtCQUFtQixTQUFRLEtBQUs7SUFJM0MsWUFBWSxPQUFnQyxFQUFFLFVBQWtCLEVBQUUsYUFBeUMsRUFBRTtRQUMzRyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEIsSUFBSSxDQUFDLElBQUksR0FBRyxvQkFBb0IsQ0FBQztRQUNqQyxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztRQUNwQixJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQztJQUM1QixDQUFDO0NBQ0YifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fin.cx/compatibility",
3
- "version": "5.2.1",
3
+ "version": "5.3.0",
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, the document-image archive (document.xml and ZIP), and a payroll program's Buchungsliste read into journal drafts",
6
6
  "main": "dist_ts/index.js",
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "devDependencies": {
53
53
  "@fin.cx/skr": "^8.0.0",
54
- "@git.zone/tsbuild": "^5.1.2",
54
+ "@git.zone/tsbuild": "^5.2.0",
55
55
  "@git.zone/tsrun": "^3.0.2",
56
56
  "@git.zone/tstest": "^7.2.0",
57
57
  "@types/node": "^26.6.3"
package/readme.md CHANGED
@@ -124,14 +124,17 @@ How a row is read:
124
124
  - **Kept, not booked**: the Buchungsdatum and the Buchungsperiode stand on the row (`buchungsDatum`, `buchungsperiode`); a draft is dated by its Belegdatum, as a Buchungsstapel row is.
125
125
  - **The chart is your skr's.** skr 8's SKR 03 knows 8611 "Verrechnete sonstige Sachbezüge aus Fahrzeug-Gestellung 19 % USt" as an Automatikkonto at 19 %: a company car's row onto it without a key books the VAT out of the amount. skr 7 knows 8611 as no Automatikkonto, and the same row books no VAT.
126
126
 
127
- Refused with `CompatibilityError` `invalid_buchungsliste`, the message naming the line and the row, and `details` the `line`, the `row`, the `field` (its column's name as the file states it) and its `value`:
128
-
129
- - a file that begins with the byte order mark of UTF-8, or has no first line; a first line whose names are separated by none of semicolon, tab and comma;
130
- - a required column missing (Belegdatum, Buchungsbetrag, Sollkonto, Habenkonto), each named, or two columns of one field;
131
- - a row of another number of fields than the first line; a quote never closed, or text after a closing quote;
132
- - a day not TT.MM.JJJJ (or none in the Belegdatum); an amount that is not digits with, if any, a decimal comma and at most 2 decimals, at most 10 digits before it (dots may group the thousands, a minus sign may lead it), or 0; an account not of 1 to 9 digits; a Steuerschlüssel skr does not know; a Buchungsperiode not of 1 or 2 digits; a Währung other than EUR (or empty);
133
- - a row that states Zusatzangaben, an EU Land or an EU %: this version maps none of them (the § 13b and OSS cases need a decision it does not make);
134
- - the first row skr cannot book (a tax whose account cannot be told) or whose draft its check refuses (`details.errors`).
127
+ Refused with `CompatibilityError` `invalid_buchungsliste`, the message naming the line and the row, and `details` why (`reason`, `TBuchungslisteRefusalReason`), the `line`, the `row`, the `field` (its column's name as the file states it) and its `value`:
128
+
129
+ - `unreadable`: a file that begins with the byte order mark of UTF-8, or has no first line; a first line whose names are separated by none of semicolon, tab and comma; a required column missing (Belegdatum, Buchungsbetrag, Sollkonto, Habenkonto), each named, or two columns of one field; a row of another number of fields than the first line; a quote never closed, or text after a closing quote;
130
+ - `field_malformed`: a day not TT.MM.JJJJ (or none in the Belegdatum); an amount that is not digits with, if any, a decimal comma and at most 2 decimals, at most 10 digits before it (dots may group the thousands, a minus sign may lead it), or 0; an account not of 1 to 9 digits; a Buchungsperiode not of 1 or 2 digits;
131
+ - `bu_key_unknown`: a Steuerschlüssel skr does not know;
132
+ - `currency_unsupported`: a Währung other than EUR (or empty);
133
+ - `field_unmapped`: a row that states Zusatzangaben, an EU Land or an EU %: this version maps none of them (the § 13b and OSS cases need a decision it does not make);
134
+ - `tax_account_unclear`: the first row skr cannot book, a tax whose account cannot be told;
135
+ - `row_invalid`: the first row whose draft skr's check refuses (`details.errors`).
136
+
137
+ The `reason` lets a consumer tell its user why without the message, which states the file's values.
135
138
 
136
139
  **Unconfirmed until a real export of lohn+gehalt has been read.** No such export has been seen. The field names lohn+gehalt writes in the first line (a secondary source names `Belegdatum;Belegnummer;Buchungstext;Buchungsbetrag;Währung;Sollkonto;Habenkonto;Kostenstelle 1`), the delimiter, the quoting and the line ending are not known; hence the reader takes the columns by name and the delimiter from the first line (the first of semicolon, tab and comma outside quotes), takes a field in double quotes with a quote written twice inside, a line break inside quotes, lines ending in CRLF, LF or CR, and skips a line that states nothing. Unconfirmed as well: that "Kostenstelle 2" is the second cost-centre level (KOST2), how the file writes an empty numeric field (a `0` in Zusatzangaben or EU % is refused, as any value there) and a Steuerschlüssel (written with a leading zero, `09`, or as `0`, it is refused), whether the Belegnummer already holds the Nummernkreis, whether a Währung column is written as `EUR`, and whether amounts are ever negative.
137
140
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@fin.cx/compatibility',
6
- version: '5.2.1',
6
+ version: '5.3.0',
7
7
  description: 'Exchange formats of third-party accounting systems: the EXTF Buchungsstapel in Windows-1252 on the rows of @fin.cx/skr, the document-image archive (document.xml and ZIP), and a payroll program\'s Buchungsliste read into journal drafts'
8
8
  }
@@ -1,8 +1,13 @@
1
1
  import * as plugins from './plugins.js';
2
- import { CompatibilityError, type ICompatibilityErrorDetails } from '../error.js';
2
+ import { CompatibilityError, type ICompatibilityErrorDetails, type TBuchungslisteRefusalReason } from '../error.js';
3
3
  import { decodeWindows1252 } from '../encoding/index.js';
4
4
 
5
- export { CompatibilityError, type TCompatibilityErrorCode, type ICompatibilityErrorDetails } from '../error.js';
5
+ export {
6
+ CompatibilityError,
7
+ type TCompatibilityErrorCode,
8
+ type ICompatibilityErrorDetails,
9
+ type TBuchungslisteRefusalReason,
10
+ } from '../error.js';
6
11
 
7
12
  export type IDatevBuchungsstapelRow = plugins.skrCore.IDatevBuchungsstapelRow;
8
13
 
@@ -158,9 +163,12 @@ interface IRecord {
158
163
  fields: string[];
159
164
  }
160
165
 
161
- /** A Buchungsliste that cannot be read as it is. */
162
- const refusal = (messageArg: string, detailsArg: ICompatibilityErrorDetails): CompatibilityError =>
163
- new CompatibilityError('invalid_buchungsliste', messageArg, detailsArg);
166
+ /** A Buchungsliste that cannot be read as it is, and why. */
167
+ const refusal = (
168
+ reasonArg: TBuchungslisteRefusalReason,
169
+ messageArg: string,
170
+ detailsArg: Omit<ICompatibilityErrorDetails, 'reason'>,
171
+ ): CompatibilityError => new CompatibilityError('invalid_buchungsliste', messageArg, { reason: reasonArg, ...detailsArg });
164
172
 
165
173
  /**
166
174
  * The delimiter the first line separates its names by: the first of semicolon, tab and comma that stands in it outside
@@ -179,7 +187,7 @@ const delimiterOf = (firstLineArg: string, lineArg: number): string => {
179
187
  }
180
188
  const delimiter = DELIMITERS.find((delimiterArg) => outside.has(delimiterArg));
181
189
  if (delimiter === undefined) {
182
- throw refusal(`line ${lineArg}: the field names of the first line are separated by none of semicolon, tab and comma`, { line: lineArg });
190
+ throw refusal('unreadable', `line ${lineArg}: the field names of the first line are separated by none of semicolon, tab and comma`, { line: lineArg });
183
191
  }
184
192
  return delimiter;
185
193
  };
@@ -228,7 +236,7 @@ const recordsOf = (textArg: string, delimiterArg: string): IRecord[] => {
228
236
  recordLine = line;
229
237
  }
230
238
  } else if (closed) {
231
- throw refusal(`line ${line}: field ${fields.length + 1} has text after its closing quote`, { line });
239
+ throw refusal('unreadable', `line ${line}: field ${fields.length + 1} has text after its closing quote`, { line });
232
240
  } else if (char === '"' && current === '') {
233
241
  quoted = true;
234
242
  } else {
@@ -236,7 +244,7 @@ const recordsOf = (textArg: string, delimiterArg: string): IRecord[] => {
236
244
  }
237
245
  }
238
246
  if (quoted) {
239
- throw refusal(`line ${recordLine}: field ${fields.length + 1} opens a quote that is never closed`, { line: recordLine });
247
+ throw refusal('unreadable', `line ${recordLine}: field ${fields.length + 1} opens a quote that is never closed`, { line: recordLine });
240
248
  }
241
249
  // the last record, where the text does not end in a line break
242
250
  if (current !== '' || closed || fields.length > 0) {
@@ -287,19 +295,19 @@ const centsOf = (valueArg: string): number | undefined => {
287
295
  */
288
296
  export const readBuchungsliste = (bytesArg: Uint8Array): IBuchungsliste => {
289
297
  if (bytesArg[0] === 0xef && bytesArg[1] === 0xbb && bytesArg[2] === 0xbf) {
290
- throw refusal('the Buchungsliste begins with the byte order mark of UTF-8; it is read as Windows-1252 (ANSI)', { line: 1 });
298
+ throw refusal('unreadable', 'the Buchungsliste begins with the byte order mark of UTF-8; it is read as Windows-1252 (ANSI)', { line: 1 });
291
299
  }
292
300
  const text = decodeWindows1252(bytesArg);
293
301
  const lines = text.split(/\r\n|\n|\r/u);
294
302
  // the first line that states anything names the fields
295
303
  const firstLineIndex = lines.findIndex((lineArg) => /[^\s;,"]/u.test(lineArg));
296
304
  if (firstLineIndex < 0) {
297
- throw refusal('the Buchungsliste has no first line naming its fields', {});
305
+ throw refusal('unreadable', 'the Buchungsliste has no first line naming its fields', {});
298
306
  }
299
307
  const delimiter = delimiterOf(lines[firstLineIndex], firstLineIndex + 1);
300
308
  const [captionRecord, ...dataRecords] = recordsOf(text, delimiter).filter((recordArg) => !isBlank(recordArg));
301
309
  if (captionRecord === undefined) {
302
- throw refusal('the Buchungsliste has no first line naming its fields', {});
310
+ throw refusal('unreadable', 'the Buchungsliste has no first line naming its fields', {});
303
311
  }
304
312
  const captions = captionRecord.fields.map((fieldArg) => fieldArg.trim());
305
313
 
@@ -319,6 +327,7 @@ export const readBuchungsliste = (bytesArg: Uint8Array): IBuchungsliste => {
319
327
  const earlier = columnOf.get(field);
320
328
  if (earlier !== undefined) {
321
329
  throw refusal(
330
+ 'unreadable',
322
331
  `line ${captionRecord.line}: columns ${earlier + 1} "${captions[earlier]}" and ${columnArg + 1} "${captionArg}" both state the ${FIELD_NAMES[field]}`,
323
332
  { line: captionRecord.line, field: captionArg },
324
333
  );
@@ -327,7 +336,7 @@ export const readBuchungsliste = (bytesArg: Uint8Array): IBuchungsliste => {
327
336
  });
328
337
  const missing = REQUIRED_FIELDS.filter((fieldArg) => !columnOf.has(fieldArg));
329
338
  if (missing.length > 0) {
330
- throw refusal(`line ${captionRecord.line}: the Buchungsliste has no column ${missing.map((fieldArg) => FIELD_NAMES[fieldArg]).join(', ')}`, {
339
+ throw refusal('unreadable', `line ${captionRecord.line}: the Buchungsliste has no column ${missing.map((fieldArg) => FIELD_NAMES[fieldArg]).join(', ')}`, {
331
340
  line: captionRecord.line,
332
341
  field: FIELD_NAMES[missing[0]],
333
342
  });
@@ -342,14 +351,17 @@ export const readBuchungsliste = (bytesArg: Uint8Array): IBuchungsliste => {
342
351
  const row = indexArg + 1;
343
352
  const { line } = recordArg;
344
353
  if (recordArg.fields.length !== captions.length) {
345
- throw refusal(`row ${row} (line ${line}) has ${recordArg.fields.length} fields, not the ${captions.length} of the first line`, { row, line });
354
+ throw refusal('unreadable', `row ${row} (line ${line}) has ${recordArg.fields.length} fields, not the ${captions.length} of the first line`, { row, line });
346
355
  }
347
356
  const at = (fieldArg: TBuchungslisteField): string => {
348
357
  const column = columnOf.get(fieldArg);
349
358
  return column === undefined ? '' : recordArg.fields[column].trim();
350
359
  };
351
- const malformed = (fieldArg: TBuchungslisteField, messageArg: string): CompatibilityError =>
352
- refusal(`row ${row} (line ${line}): ${messageArg}`, { row, line, field: nameOf(fieldArg), value: at(fieldArg) });
360
+ const malformed = (
361
+ fieldArg: TBuchungslisteField,
362
+ messageArg: string,
363
+ reasonArg: TBuchungslisteRefusalReason = 'field_malformed',
364
+ ): CompatibilityError => refusal(reasonArg, `row ${row} (line ${line}): ${messageArg}`, { row, line, field: nameOf(fieldArg), value: at(fieldArg) });
353
365
  const day = (fieldArg: TBuchungslisteField): Date | undefined => {
354
366
  if (at(fieldArg) === '') return undefined;
355
367
  const value = dayOf(at(fieldArg));
@@ -363,12 +375,12 @@ export const readBuchungsliste = (bytesArg: Uint8Array): IBuchungsliste => {
363
375
 
364
376
  for (const field of UNMAPPED_FIELDS) {
365
377
  if (at(field) !== '') {
366
- throw malformed(field, `the row states ${nameOf(field)} "${at(field)}"; this version maps no Zusatzangaben (§ 13b), EU Land or EU %`);
378
+ throw malformed(field, `the row states ${nameOf(field)} "${at(field)}"; this version maps no Zusatzangaben (§ 13b), EU Land or EU %`, 'field_unmapped');
367
379
  }
368
380
  }
369
381
  const currency = at('waehrung');
370
382
  if (currency !== '' && currency !== 'EUR') {
371
- throw malformed('waehrung', `the row is in ${currency}; these books are in euro`);
383
+ throw malformed('waehrung', `the row is in ${currency}; these books are in euro`, 'currency_unsupported');
372
384
  }
373
385
  const belegDatum = day('belegdatum');
374
386
  if (!belegDatum) throw malformed('belegdatum', `the row states no ${nameOf('belegdatum')}`);
@@ -392,6 +404,7 @@ export const readBuchungsliste = (bytesArg: Uint8Array): IBuchungsliste => {
392
404
  throw malformed(
393
405
  'steuerschluessel',
394
406
  `the ${nameOf('steuerschluessel')} "${key}" is no DATEV key these books know (${Object.keys(plugins.skrCore.BU_KEY_RULES).join(', ')})`,
407
+ 'bu_key_unknown',
395
408
  );
396
409
  }
397
410
  const texts = {
@@ -485,13 +498,15 @@ export const importBuchungsliste = (
485
498
  draft = plugins.skrCore.journalDraftOfDatevRow(datevRow, policyArg);
486
499
  } catch (error) {
487
500
  if (error instanceof plugins.skrCore.DatevImportError) {
488
- throw refusal(`row ${row} (line ${line}): ${error.message}`, { row, line });
501
+ // skr refuses a row's draft for a tax whose account cannot be told; any other refusal of its is a row that gives no entry
502
+ const reason = error.code === 'extf_tax_account_unclear' ? 'tax_account_unclear' : 'row_invalid';
503
+ throw refusal(reason, `row ${row} (line ${line}): ${error.message}`, { row, line });
489
504
  }
490
505
  throw error;
491
506
  }
492
507
  const validation = plugins.skrCore.validateJournalDraft(draft, policyArg);
493
508
  if (!validation.valid) {
494
- throw refusal(`row ${row} (line ${line}) gives no valid entry: ${validation.errors.join('; ')}`, { row, line, errors: validation.errors });
509
+ throw refusal('row_invalid', `row ${row} (line ${line}) gives no valid entry: ${validation.errors.join('; ')}`, { row, line, errors: validation.errors });
495
510
  }
496
511
  return { row, buchungslisteRow, datevRow, draft };
497
512
  });
package/ts/error.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  * centres its record does not state (stored before 4.1) and no rows sent were given; the message names it;
15
15
  * - `invalid_buchungsliste`: a Buchungsliste that cannot be read or booked as it is: no header line, a required
16
16
  * column missing, a field that is not of its format, a field this version does not map, or a row that gives no
17
- * valid entry; `details` names the line, the row and the field where it can.
17
+ * valid entry; `details` names why (`reason`), the line, the row and the field where it can.
18
18
  */
19
19
  export type TCompatibilityErrorCode =
20
20
  | 'invalid_bookings'
@@ -25,8 +25,35 @@ export type TCompatibilityErrorCode =
25
25
  | 'handed_over_cost_centres_unknown'
26
26
  | 'invalid_buchungsliste';
27
27
 
28
+ /**
29
+ * Why a Buchungsliste was refused (`invalid_buchungsliste`), so a consumer can tell its user without reading the
30
+ * message:
31
+ * - `unreadable`: the text is no list of rows of the first line's fields: a byte order mark of UTF-8, no first line,
32
+ * no delimiter, a quote never closed or text after a closing quote, a required column missing or two columns of
33
+ * one field, a row of another number of fields;
34
+ * - `field_malformed`: a field not of its format (a day, an amount or 0, an account, a Buchungsperiode), or no
35
+ * Belegdatum;
36
+ * - `field_unmapped`: a row that states Zusatzangaben, an EU Land or an EU %, which this version does not map;
37
+ * - `currency_unsupported`: a Währung other than EUR;
38
+ * - `bu_key_unknown`: a Steuerschlüssel `@fin.cx/skr` does not know;
39
+ * - `tax_account_unclear`: a row with a tax where the account it is computed on cannot be told (skr's
40
+ * `extf_tax_account_unclear`);
41
+ * - `row_invalid`: a row whose entry skr refuses otherwise; where its check (`validateJournalDraft`) refused it, what
42
+ * the check found in `details.errors`.
43
+ */
44
+ export type TBuchungslisteRefusalReason =
45
+ | 'unreadable'
46
+ | 'field_malformed'
47
+ | 'field_unmapped'
48
+ | 'currency_unsupported'
49
+ | 'bu_key_unknown'
50
+ | 'tax_account_unclear'
51
+ | 'row_invalid';
52
+
28
53
  /** Where a refusal of a file read stands, as far as it is known; empty for a file written. */
29
54
  export interface ICompatibilityErrorDetails {
55
+ /** why a Buchungsliste was refused; stated on every `invalid_buchungsliste` */
56
+ reason?: TBuchungslisteRefusalReason;
30
57
  /** the data row, from 1 */
31
58
  row?: number;
32
59
  /** the line of the file, from 1 */