@fin.cx/einvoice 10.0.1 → 10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/einvoice.d.ts +2 -0
  3. package/dist_ts/einvoice.js +7 -13
  4. package/dist_ts/formats/cii/cii.decoder.d.ts +11 -3
  5. package/dist_ts/formats/cii/cii.decoder.js +27 -8
  6. package/dist_ts/formats/cii/cii.encoder.d.ts +12 -0
  7. package/dist_ts/formats/cii/cii.encoder.js +36 -1
  8. package/dist_ts/formats/cii/cii.types.js +2 -1
  9. package/dist_ts/formats/cii/facturx/facturx.encoder.js +12 -8
  10. package/dist_ts/formats/cii/zugferd/zugferd.encoder.js +12 -8
  11. package/dist_ts/formats/semantic/semantic.adapter.d.ts +0 -4
  12. package/dist_ts/formats/semantic/semantic.adapter.js +7 -18
  13. package/dist_ts/formats/ubl/generic/ubl.encoder.d.ts +6 -1
  14. package/dist_ts/formats/ubl/generic/ubl.encoder.js +40 -8
  15. package/dist_ts/formats/ubl/ubl.decoder.d.ts +11 -0
  16. package/dist_ts/formats/ubl/ubl.decoder.js +30 -1
  17. package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.js +3 -3
  18. package/dist_ts/formats/utils/delivery.address.d.ts +18 -0
  19. package/dist_ts/formats/utils/delivery.address.js +30 -0
  20. package/dist_ts/formats/utils/document.totals.d.ts +5 -4
  21. package/dist_ts/formats/utils/document.totals.js +24 -8
  22. package/dist_ts/formats/utils/stated.values.js +4 -2
  23. package/dist_ts/formats/utils/vat.category.d.ts +146 -55
  24. package/dist_ts/formats/utils/vat.category.js +357 -69
  25. package/dist_ts/formats/validation/vat-categories.validator.d.ts +14 -15
  26. package/dist_ts/formats/validation/vat-categories.validator.js +123 -85
  27. package/package.json +3 -3
  28. package/readme.md +55 -19
  29. package/ts/00_commitinfo_data.ts +1 -1
  30. package/ts/einvoice.ts +8 -14
  31. package/ts/formats/cii/cii.decoder.ts +28 -7
  32. package/ts/formats/cii/cii.encoder.ts +36 -0
  33. package/ts/formats/cii/cii.types.ts +1 -0
  34. package/ts/formats/cii/facturx/facturx.encoder.ts +12 -7
  35. package/ts/formats/cii/zugferd/zugferd.encoder.ts +12 -7
  36. package/ts/formats/semantic/semantic.adapter.ts +6 -15
  37. package/ts/formats/ubl/generic/ubl.encoder.ts +40 -7
  38. package/ts/formats/ubl/ubl.decoder.ts +31 -0
  39. package/ts/formats/ubl/xrechnung/xrechnung.decoder.ts +2 -2
  40. package/ts/formats/utils/delivery.address.ts +36 -0
  41. package/ts/formats/utils/document.totals.ts +38 -11
  42. package/ts/formats/utils/stated.values.ts +4 -1
  43. package/ts/formats/utils/vat.category.ts +426 -95
  44. package/ts/formats/validation/vat-categories.validator.ts +169 -88
@@ -1,28 +1,111 @@
1
1
  import { EInvoiceFormatError } from '../../errors.js';
2
+ /** Every VAT category code EN 16931 allows, in the order of `TVatCategoryCode` */
3
+ export const VAT_CATEGORY_CODES = ['S', 'Z', 'E', 'AE', 'K', 'G', 'O', 'L', 'M'];
2
4
  /**
3
- * The VAT category of every line of a document: reverse charge (`AE`) when the
4
- * document states it, standard rated (`S`) otherwise.
5
+ * Whether a value is a VAT category code EN 16931 allows
6
+ * @param value The value
7
+ */
8
+ export const isVatCategoryCode = (value) => typeof value === 'string' && VAT_CATEGORY_CODES.includes(value);
9
+ /**
10
+ * The categories whose VAT breakdown states an exemption reason, as a code
11
+ * (BT-121) or a text (BT-120): exempt (BR-E-10), reverse charge (BR-AE-10),
12
+ * intra-community supply (BR-IC-10), export (BR-G-10) and not subject to VAT
13
+ * (BR-O-10). The others state none (BR-S-10, BR-Z-10, BR-AF-10, BR-AG-10).
14
+ */
15
+ export const VAT_CATEGORIES_WITH_EXEMPTION = ['E', 'AE', 'K', 'G', 'O'];
16
+ /**
17
+ * The CEF VATEX code list, as the CEN/TC 434 EN 16931 validation artefacts
18
+ * 1.3.16 check a VAT exemption reason code (BT-121) against it (BR-CL-22,
19
+ * compared in upper case)
20
+ */
21
+ export const VATEX_CODES = new Set(('VATEX-EU-79-C VATEX-EU-132 VATEX-EU-132-1A VATEX-EU-132-1B VATEX-EU-132-1C VATEX-EU-132-1D VATEX-EU-132-1E ' +
22
+ 'VATEX-EU-132-1F VATEX-EU-132-1G VATEX-EU-132-1H VATEX-EU-132-1I VATEX-EU-132-1J VATEX-EU-132-1K VATEX-EU-132-1L ' +
23
+ 'VATEX-EU-132-1M VATEX-EU-132-1N VATEX-EU-132-1O VATEX-EU-132-1P VATEX-EU-132-1Q VATEX-EU-135-1 VATEX-EU-143 ' +
24
+ 'VATEX-EU-143-1A VATEX-EU-143-1B VATEX-EU-143-1C VATEX-EU-143-1D VATEX-EU-143-1E VATEX-EU-143-1F VATEX-EU-143-1FA ' +
25
+ 'VATEX-EU-143-1G VATEX-EU-143-1H VATEX-EU-143-1I VATEX-EU-143-1J VATEX-EU-143-1K VATEX-EU-143-1L VATEX-EU-144 ' +
26
+ 'VATEX-EU-146-1E VATEX-EU-159 VATEX-EU-309 VATEX-EU-148 VATEX-EU-148-A VATEX-EU-148-B VATEX-EU-148-C VATEX-EU-148-D ' +
27
+ 'VATEX-EU-148-E VATEX-EU-148-F VATEX-EU-148-G VATEX-EU-151 VATEX-EU-151-1A VATEX-EU-151-1AA VATEX-EU-151-1B ' +
28
+ 'VATEX-EU-151-1C VATEX-EU-151-1D VATEX-EU-151-1E VATEX-EU-G VATEX-EU-O VATEX-EU-IC VATEX-EU-AE VATEX-EU-D VATEX-EU-F ' +
29
+ 'VATEX-EU-I VATEX-EU-J VATEX-FR-FRANCHISE VATEX-FR-CNWVAT VATEX-EU-153 VATEX-FR-CGI261-1 VATEX-FR-CGI261-2 ' +
30
+ 'VATEX-FR-CGI261-3 VATEX-FR-CGI261-4 VATEX-FR-CGI261-5 VATEX-FR-CGI261-7 VATEX-FR-CGI261-8 VATEX-FR-CGI261A ' +
31
+ 'VATEX-FR-CGI261B VATEX-FR-CGI261C-1 VATEX-FR-CGI261C-2 VATEX-FR-CGI261C-3 VATEX-FR-CGI261D-1 VATEX-FR-CGI261D-1BIS ' +
32
+ 'VATEX-FR-CGI261D-2 VATEX-FR-CGI261D-3 VATEX-FR-CGI261D-4 VATEX-FR-CGI261E-1 VATEX-FR-CGI261E-2 VATEX-FR-CGI277A ' +
33
+ 'VATEX-FR-CGI275 VATEX-FR-298SEXDECIESA VATEX-FR-CGI295 VATEX-FR-AE').split(' '));
34
+ /**
35
+ * Whether a VAT exemption reason code is on the CEF VATEX code list (BR-CL-22)
36
+ * @param code The code
37
+ */
38
+ export const isVatexCode = (code) => VATEX_CODES.has(code.trim().toUpperCase());
39
+ /**
40
+ * The VAT category of an item: the one it states (`vatCategory`, BT-151), else
41
+ * reverse charge (AE) when the document states `reverseCharge`, standard rated
42
+ * (S) otherwise.
5
43
  * @param accountingDoc The document
44
+ * @param item The item
45
+ */
46
+ export const getItemVatCategory = (accountingDoc, item) => item.vatCategory ?? (accountingDoc.reverseCharge ? 'AE' : 'S');
47
+ /**
48
+ * The exemption reason an item states: its VATEX code (BT-121) and its text
49
+ * (BT-120), each trimmed; undefined when it states neither
50
+ * @param item The item
6
51
  */
7
- export const getVatCategory = (accountingDoc) => accountingDoc.reverseCharge ? 'AE' : 'S';
52
+ export const getItemVatExemption = (item) => {
53
+ const code = item.vatExemptionReasonCode?.trim();
54
+ const reason = item.vatExemptionReason?.trim();
55
+ if (!code && !reason) {
56
+ return undefined;
57
+ }
58
+ return { ...(code ? { code } : {}), ...(reason ? { reason } : {}) };
59
+ };
8
60
  /**
9
- * The exemption reason a reverse charge VAT breakdown states (BR-AE-10): the
10
- * code `VATEX-EU-AE` and the wording the law prescribes, "Steuerschuldnerschaft
11
- * des Leistungsempfängers" (§ 14a Abs. 1 and 5 UStG). A document in another
12
- * language may use the wording of Article 226 Nr. 11a of the VAT Directive in
13
- * that language, "Reverse charge" in English (Abschnitt 14a.1 Abs. 6 Satz 2
14
- * UStAE). Other categories state none.
61
+ * The exemption reason a VAT breakdown of a category states when none of its
62
+ * items states one.
63
+ * - Reverse charge (AE): the code `VATEX-EU-AE` and the wording the law
64
+ * prescribes, "Steuerschuldnerschaft des Leistungsempfängers" (§ 14a Abs. 1
65
+ * and 5 UStG). A document in another language may use the wording of
66
+ * Article 226 Nr. 11a of the VAT Directive in that language, "Reverse charge"
67
+ * in English (Abschnitt 14a.1 Abs. 6 Satz 2 UStAE).
68
+ * - Intra-community supply (K), export outside the EU (G) and not subject to
69
+ * VAT (O): the VATEX code that means the category, `VATEX-EU-IC`,
70
+ * `VATEX-EU-G` and `VATEX-EU-O`, which BR-IC-10, BR-G-10 and BR-O-10 accept.
71
+ * - Exempt (E): none. The reason depends on the exemption applied, which only
72
+ * the issuer knows; a document with an exempt item that states none is
73
+ * refused (BR-E-10).
15
74
  * @param category The VAT category
16
75
  * @param language The document language
17
76
  */
18
- export const getVatExemption = (category, language) => category === 'AE'
19
- ? {
20
- code: 'VATEX-EU-AE',
21
- reason: (language ?? '').toLowerCase().startsWith('de')
22
- ? 'Steuerschuldnerschaft des Leistungsempfängers'
23
- : 'Reverse charge',
77
+ export const getDefaultVatExemption = (category, language) => {
78
+ switch (category) {
79
+ case 'AE':
80
+ return {
81
+ code: 'VATEX-EU-AE',
82
+ reason: (language ?? '').toLowerCase().startsWith('de') ? 'Steuerschuldnerschaft des Leistungsempfängers' : 'Reverse charge',
83
+ };
84
+ case 'K':
85
+ return { code: 'VATEX-EU-IC' };
86
+ case 'G':
87
+ return { code: 'VATEX-EU-G' };
88
+ case 'O':
89
+ return { code: 'VATEX-EU-O' };
90
+ default:
91
+ return undefined;
24
92
  }
25
- : undefined;
93
+ };
94
+ /**
95
+ * The exemption reason a VAT breakdown states: the code and the text its items
96
+ * state, each completed by the category's default where they state none
97
+ * (`getDefaultVatExemption`); undefined when there is neither
98
+ * @param stated The exemption the items state
99
+ * @param categoryDefault The category's default
100
+ */
101
+ export const mergeVatExemption = (stated, categoryDefault) => {
102
+ const code = stated?.code ?? categoryDefault?.code;
103
+ const reason = stated?.reason ?? categoryDefault?.reason;
104
+ if (!code && !reason) {
105
+ return undefined;
106
+ }
107
+ return { ...(code ? { code } : {}), ...(reason ? { reason } : {}) };
108
+ };
26
109
  /**
27
110
  * Whether a VAT rate is a number not greater than zero; a rate that is no
28
111
  * number is refused as such (`findInvalidItemAmounts`), not as BR-S-05
@@ -30,70 +113,275 @@ export const getVatExemption = (category, language) => category === 'AE'
30
113
  */
31
114
  export const isRateNotAboveZero = (rate) => typeof rate === 'number' && Number.isFinite(rate) && !(rate > 0);
32
115
  /**
33
- * The first line of a document that is not reverse charge whose VAT rate is not
34
- * greater than zero. The encoders write every such line as standard rated (S),
35
- * and EN 16931 BR-S-05 asks a standard rated line for a rate greater than zero;
36
- * the category the line has (zero rated Z, exempt E, intra-community supply K,
37
- * export G, not subject to VAT O) cannot be stated until an item carries a VAT
38
- * category of its own.
39
- * @param items The document's items
116
+ * The refusal or finding for a standard rated line whose VAT rate is not
117
+ * greater than zero (BR-S-05)
118
+ * @param line The line index and its rate
119
+ * @param statedCategory Whether the item states the category S itself
120
+ */
121
+ export const standardRatedLineWithoutRateMessage = (line, statedCategory = false) => `In an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "Standard rated" the Invoiced item VAT rate (BT-152) shall be greater than zero; items[${line.index}].vatPercentage is ${String(line.vatPercentage)}. ` +
122
+ (statedCategory
123
+ ? `items[${line.index}].vatCategory states S`
124
+ : `An item outside reverse charge that states no category (items[${line.index}].vatCategory) is standard rated (S); an item that is zero rated, exempt, an intra-community supply, an export or not subject to VAT states its category, Z, E, K, G or O`);
125
+ /** The package's own check: the items of one VAT breakdown state different exemption reasons */
126
+ export const VAT_EXEMPTION_DIFFERS = 'EINVOICE-VAT-EXEMPTION-DIFFERS';
127
+ /**
128
+ * The item VAT rate each category allows: greater than zero for S (BR-S-05);
129
+ * 0 for Z, E, AE, K and G (BR-Z-05, BR-E-05, BR-AE-05, BR-IC-05, BR-G-05);
130
+ * 0 or greater for L and M (BR-AF-05, BR-AG-05). An item not subject to VAT
131
+ * (O) is written without a rate (BR-O-05), so it states 0.
40
132
  */
41
- export const findStandardRatedLineWithoutRate = (items) => {
42
- const index = (items ?? []).findIndex((item) => isRateNotAboveZero(item.vatPercentage));
43
- return index < 0 ? undefined : { index, vatPercentage: items[index].vatPercentage };
133
+ const RATE_RULES = {
134
+ S: { ruleId: 'BR-S-05', allows: (rate) => rate > 0, expected: 'greater than zero' },
135
+ Z: { ruleId: 'BR-Z-05', allows: (rate) => rate === 0, expected: '0' },
136
+ E: { ruleId: 'BR-E-05', allows: (rate) => rate === 0, expected: '0' },
137
+ AE: { ruleId: 'BR-AE-05', allows: (rate) => rate === 0, expected: '0' },
138
+ K: { ruleId: 'BR-IC-05', allows: (rate) => rate === 0, expected: '0' },
139
+ G: { ruleId: 'BR-G-05', allows: (rate) => rate === 0, expected: '0' },
140
+ O: { ruleId: 'BR-O-05', allows: (rate) => rate === 0, expected: '0, as an item not subject to VAT is written without a VAT rate' },
141
+ L: { ruleId: 'BR-AF-05', allows: (rate) => rate >= 0, expected: '0 or greater' },
142
+ M: { ruleId: 'BR-AG-05', allows: (rate) => rate >= 0, expected: '0 or greater' },
44
143
  };
45
144
  /**
46
- * The refusal or finding for such a line
47
- * @param line The line
145
+ * BR-AF-05 as the CII binding of the CEN/TC 434 artefacts 1.3.16 checks it:
146
+ * `ram:RateApplicablePercent > 0`, where the rule text and the UBL binding
147
+ * allow 0. A CII document with IGIC at 0 fails the official check, so it is
148
+ * not written.
48
149
  */
49
- export const standardRatedLineWithoutRateMessage = (line) => `In an Invoice line (BG-25) where the Invoiced item VAT category code (BT-151) is "Standard rated" the Invoiced item VAT rate (BT-152) shall be greater than zero; items[${line.index}].vatPercentage is ${String(line.vatPercentage)}. A line outside reverse charge is written as standard rated (S); its category, zero rated, exempt, intra-community supply or export (Z, E, K, G or O), cannot be stated until an item carries a VAT category of its own`;
150
+ const CII_IGIC_RATE_RULE = {
151
+ ruleId: 'BR-AF-05',
152
+ allows: (rate) => rate > 0,
153
+ expected: 'greater than zero in CII, whose binding of the CEN artefacts checks BR-AF-05 so; UBL allows 0',
154
+ };
155
+ /** The rule a VAT breakdown of each category breaks by stating, or by lacking, an exemption reason */
156
+ const EXEMPTION_RULES = {
157
+ S: 'BR-S-10',
158
+ Z: 'BR-Z-10',
159
+ E: 'BR-E-10',
160
+ AE: 'BR-AE-10',
161
+ K: 'BR-IC-10',
162
+ G: 'BR-G-10',
163
+ O: 'BR-O-10',
164
+ L: 'BR-AF-10',
165
+ M: 'BR-AG-10',
166
+ };
50
167
  /**
51
- * Refuses a document whose lines cannot be written with a valid VAT category,
52
- * naming the rule: a line outside reverse charge whose rate is not greater than
53
- * zero (BR-S-05), and a reverse charge document that lacks what EN 16931
54
- * requires of one; no value is put in place of a missing one.
55
- * - BR-AE-05: every line of a reverse charge document has the VAT rate 0; the
56
- * recipient owes the tax, and the invoice states none (§ 14a Abs. 5 Satz 2
57
- * UStG; a stated amount would be owed under § 14c Abs. 1 UStG).
58
- * - BR-AE-02: the seller states a VAT identifier (BT-31) or a tax
59
- * registration identifier (BT-32, `registrationDetails.taxNumber`, the
60
- * Steuernummer, which § 14 Abs. 4 Satz 1 Nr. 2 UStG allows instead), and the
61
- * buyer a VAT identifier (BT-48) or a legal registration identifier (BT-47).
62
- * The rule also accepts a tax representative's VAT identifier (BT-63) for
63
- * the seller; the envelope cannot state one, so a seller with neither BT-31
64
- * nor BT-32 is refused.
65
- * The envelope has no place of supply, so whether a document is one for a
66
- * supply in another member state, whose invoice states the VAT identification
67
- * numbers of both parties (§ 14a Abs. 1 Satz 3 UStG), cannot be told here: a
68
- * domestic § 13b supply to a buyer based in another member state is taxed in
69
- * Germany and may state a tax number. Only what BR-AE-02 requires is checked;
70
- * the issuing application enforces § 14a Abs. 1.
168
+ * Every rule of EN 16931 on the VAT categories of a document's items that the
169
+ * envelope can break, in item order and then per document; an empty list when
170
+ * the document can be written. Amounts that are no number are not checked
171
+ * here (`findInvalidItemAmounts`).
172
+ * - The rate each category allows (BR-S-05, BR-Z-05, BR-E-05, BR-AE-05,
173
+ * BR-IC-05, BR-G-05, BR-O-05, BR-AF-05, BR-AG-05).
174
+ * - The exemption reason: stated for E, AE, K, G and O (a default for AE, K,
175
+ * G and O, `getDefaultVatExemption`), not stated for S, Z, L and M (the
176
+ * BR-x-10 rules); a code on the VATEX list (BR-CL-22); one reason per VAT
177
+ * breakdown, as a breakdown states one (`EINVOICE-VAT-EXEMPTION-DIFFERS`).
178
+ * - The parties' identifiers: for Z, E, L and M the seller VAT identifier
179
+ * (BT-31) or tax registration identifier (BT-32) (BR-Z-02, BR-E-02,
180
+ * BR-AF-02, BR-AG-02); for AE that and the buyer VAT identifier (BT-48) or
181
+ * legal registration identifier (BT-47) (BR-AE-02); for K the seller and the
182
+ * buyer VAT identifier (BR-IC-02); for G the seller VAT identifier
183
+ * (BR-G-02); for O neither VAT identifier (BR-O-02). The rules also accept
184
+ * a seller tax representative (BT-63), which the envelope cannot state.
185
+ * - An intra-community supply states the delivery date (BT-72) or the
186
+ * invoicing period (BG-14) (BR-IC-11) and the deliver to country (BT-80,
187
+ * `metadata.deliveryAddress.countryCode`) (BR-IC-12).
188
+ * - A document not subject to VAT has no item of another category (BR-O-11,
189
+ * BR-O-12).
190
+ * The rule for a standard rated item holds whether it states S or is S
191
+ * because it states no category, so an item at the rate 0 outside reverse
192
+ * charge that states no category breaks BR-S-05. Whether a document in
193
+ * reverse charge meets § 14a Abs. 1 UStG (both VAT identification numbers for
194
+ * a supply in another member state) cannot be told from the envelope, which
195
+ * has no place of supply; the issuing application enforces it.
71
196
  * @param accountingDoc The document
72
- * @param targetFormat The format being written
73
197
  */
74
- export const assertVatCategoryWritable = (accountingDoc, targetFormat) => {
75
- const refuse = (rule, message) => {
76
- throw new EInvoiceFormatError(`${rule}: ${message}`, { targetFormat, unsupportedFeatures: [rule] });
77
- };
78
- if (!accountingDoc.reverseCharge) {
79
- const line = findStandardRatedLineWithoutRate(accountingDoc.items);
80
- if (line) {
81
- refuse('BR-S-05', standardRatedLineWithoutRateMessage(line));
198
+ export const findVatCategoryViolations = (accountingDoc, syntax) => {
199
+ const violations = [];
200
+ const items = accountingDoc.items ?? [];
201
+ const categories = items.map((item) => getItemVatCategory(accountingDoc, item));
202
+ items.forEach((item, index) => {
203
+ const category = categories[index];
204
+ const rule = syntax === 'cii' && category === 'L' ? CII_IGIC_RATE_RULE : RATE_RULES[category];
205
+ if (typeof item.vatPercentage === 'number' && Number.isFinite(item.vatPercentage) && !rule.allows(item.vatPercentage)) {
206
+ violations.push({
207
+ ruleId: rule.ruleId,
208
+ field: `items[${index}].vatPercentage`,
209
+ message: category === 'S'
210
+ ? standardRatedLineWithoutRateMessage({ index, vatPercentage: item.vatPercentage }, item.vatCategory === 'S')
211
+ : `an item of the VAT category ${category} has the VAT rate ${rule.expected}; items[${index}].vatPercentage is ${String(item.vatPercentage)}`,
212
+ });
82
213
  }
83
- return;
84
- }
85
- for (const [index, item] of (accountingDoc.items ?? []).entries()) {
86
- if (item.vatPercentage !== 0) {
87
- refuse('BR-AE-05', `a reverse charge line has the VAT rate 0, items[${index}].vatPercentage is ${String(item.vatPercentage)}`);
214
+ const code = item.vatExemptionReasonCode?.trim();
215
+ if (code && !isVatexCode(code)) {
216
+ violations.push({
217
+ ruleId: 'BR-CL-22',
218
+ field: `items[${index}].vatExemptionReasonCode`,
219
+ message: `the VAT exemption reason code (BT-121) belongs to the CEF VATEX code list; items[${index}].vatExemptionReasonCode is ${code}`,
220
+ });
221
+ }
222
+ });
223
+ // one VAT breakdown per category and rate, as the encoders write them (computeDocumentTotals)
224
+ const groups = new Map();
225
+ items.forEach((item, index) => {
226
+ const key = `${categories[index]}|${item.vatPercentage}`;
227
+ const group = groups.get(key) ?? { category: categories[index], indexes: [] };
228
+ group.indexes.push(index);
229
+ groups.set(key, group);
230
+ });
231
+ for (const { category, indexes } of groups.values()) {
232
+ const stated = indexes
233
+ .map((index) => ({ index, exemption: getItemVatExemption(items[index]) }))
234
+ .filter((entry) => entry.exemption !== undefined);
235
+ const distinct = new Set(stated.map((entry) => `${entry.exemption.code ?? ''}|${entry.exemption.reason ?? ''}`));
236
+ const fields = indexes.map((index) => `items[${index}]`).join(', ');
237
+ if (distinct.size > 1) {
238
+ violations.push({
239
+ ruleId: VAT_EXEMPTION_DIFFERS,
240
+ field: stated.map((entry) => `items[${entry.index}]`).join(', '),
241
+ message: `the items of one VAT breakdown (category ${category}) state one exemption reason, as the breakdown states one (BT-120, BT-121); ${stated
242
+ .map((entry) => `items[${entry.index}] states ${[entry.exemption.code, entry.exemption.reason].filter(Boolean).join(' ')}`)
243
+ .join(', ')}`,
244
+ });
245
+ }
246
+ const withExemption = VAT_CATEGORIES_WITH_EXEMPTION.includes(category);
247
+ if (withExemption && stated.length === 0 && !getDefaultVatExemption(category, accountingDoc.language)) {
248
+ violations.push({
249
+ ruleId: EXEMPTION_RULES[category],
250
+ field: fields,
251
+ message: `a VAT breakdown of the category ${category} states a VAT exemption reason code (BT-121) or text (BT-120); ${fields} state neither vatExemptionReasonCode nor vatExemptionReason`,
252
+ });
253
+ }
254
+ if (!withExemption && stated.length > 0) {
255
+ violations.push({
256
+ ruleId: EXEMPTION_RULES[category],
257
+ field: stated.map((entry) => `items[${entry.index}]`).join(', '),
258
+ message: `a VAT breakdown of the category ${category} states no VAT exemption reason (BT-120, BT-121); ${stated
259
+ .map((entry) => `items[${entry.index}]`)
260
+ .join(', ')} state one`,
261
+ });
88
262
  }
89
263
  }
264
+ const has = (category) => categories.includes(category);
90
265
  const seller = accountingDoc.from?.registrationDetails;
91
- if (!seller?.vatId && !seller?.taxNumber) {
92
- refuse('BR-AE-02', 'a reverse charge document states the seller VAT identifier (BT-31) or tax registration identifier (BT-32), from.registrationDetails.vatId and .taxNumber are missing; the rule would also accept a tax representative (BT-63), which the envelope cannot state');
93
- }
94
266
  const buyer = accountingDoc.to?.registrationDetails;
95
- if (!buyer?.vatId && !buyer?.registrationId) {
96
- refuse('BR-AE-02', 'a reverse charge document states the buyer VAT identifier (BT-48) or legal registration identifier (BT-47), to.registrationDetails.vatId and .registrationId are missing');
267
+ const sellerVatId = !!seller?.vatId?.trim();
268
+ const sellerTaxNumber = !!seller?.taxNumber?.trim();
269
+ const buyerVatId = !!buyer?.vatId?.trim();
270
+ const sellerNeither = (rule, category) => violations.push({
271
+ ruleId: rule,
272
+ field: 'from.registrationDetails',
273
+ message: `a document with an item of the VAT category ${category} states the seller VAT identifier (BT-31) or tax registration identifier (BT-32); from.registrationDetails.vatId and .taxNumber are missing. The rule would also accept a tax representative (BT-63), which the envelope cannot state`,
274
+ });
275
+ for (const [category, rule] of [['Z', 'BR-Z-02'], ['E', 'BR-E-02'], ['L', 'BR-AF-02'], ['M', 'BR-AG-02'], ['AE', 'BR-AE-02']]) {
276
+ if (has(category) && !sellerVatId && !sellerTaxNumber) {
277
+ sellerNeither(rule, category);
278
+ }
279
+ }
280
+ if (has('AE') && !buyerVatId && !buyer?.registrationId?.trim()) {
281
+ violations.push({
282
+ ruleId: 'BR-AE-02',
283
+ field: 'to.registrationDetails',
284
+ message: 'a reverse charge document states the buyer VAT identifier (BT-48) or legal registration identifier (BT-47), to.registrationDetails.vatId and .registrationId are missing',
285
+ });
286
+ }
287
+ if (has('K') && (!sellerVatId || !buyerVatId)) {
288
+ violations.push({
289
+ ruleId: 'BR-IC-02',
290
+ field: !sellerVatId ? 'from.registrationDetails.vatId' : 'to.registrationDetails.vatId',
291
+ message: 'a document with an intra-community supply (K) states the seller VAT identifier (BT-31) and the buyer VAT identifier (BT-48) (§ 14a Abs. 3 Satz 2 UStG); ' +
292
+ [!sellerVatId ? 'from.registrationDetails.vatId' : '', !buyerVatId ? 'to.registrationDetails.vatId' : ''].filter(Boolean).join(' and ') +
293
+ ' missing. The rule would also accept a seller tax representative (BT-63), which the envelope cannot state',
294
+ });
295
+ }
296
+ if (has('K') && accountingDoc.deliveryDate === undefined && accountingDoc.periodOfPerformance === undefined) {
297
+ violations.push({
298
+ ruleId: 'BR-IC-11',
299
+ field: 'deliveryDate',
300
+ message: 'a document with an intra-community supply (K) states the actual delivery date (BT-72) or the invoicing period (BG-14); deliveryDate and periodOfPerformance are missing',
301
+ });
97
302
  }
303
+ if (has('K') && !accountingDoc.metadata?.deliveryAddress?.countryCode?.trim()) {
304
+ violations.push({
305
+ ruleId: 'BR-IC-12',
306
+ field: 'metadata.deliveryAddress.countryCode',
307
+ message: 'a document with an intra-community supply (K) states the deliver to country code (BT-80); metadata.deliveryAddress.countryCode is missing',
308
+ });
309
+ }
310
+ if (has('G') && !sellerVatId) {
311
+ violations.push({
312
+ ruleId: 'BR-G-02',
313
+ field: 'from.registrationDetails.vatId',
314
+ message: 'a document with an export outside the EU (G) states the seller VAT identifier (BT-31); from.registrationDetails.vatId is missing. The rule would also accept a seller tax representative (BT-63), which the envelope cannot state',
315
+ });
316
+ }
317
+ if (has('O') && (sellerVatId || buyerVatId)) {
318
+ violations.push({
319
+ ruleId: 'BR-O-02',
320
+ field: sellerVatId ? 'from.registrationDetails.vatId' : 'to.registrationDetails.vatId',
321
+ message: `a document with an item not subject to VAT (O) states neither the seller VAT identifier (BT-31) nor the buyer VAT identifier (BT-48); ${[
322
+ sellerVatId ? 'from.registrationDetails.vatId' : '',
323
+ buyerVatId ? 'to.registrationDetails.vatId' : '',
324
+ ]
325
+ .filter(Boolean)
326
+ .join(' and ')} stated`,
327
+ });
328
+ }
329
+ if (has('O') && categories.some((category) => category !== 'O')) {
330
+ violations.push({
331
+ ruleId: 'BR-O-11',
332
+ field: categories.map((category, index) => (category === 'O' ? '' : `items[${index}].vatCategory`)).filter(Boolean).join(', '),
333
+ message: `a document with an item not subject to VAT (O) has no item of another VAT category, as its VAT breakdown is the one of O; ${categories
334
+ .map((category, index) => (category === 'O' ? '' : `items[${index}] is ${category}`))
335
+ .filter(Boolean)
336
+ .join(', ')}`,
337
+ });
338
+ }
339
+ return violations;
340
+ };
341
+ /**
342
+ * Refuses a document whose items cannot be written with a valid VAT category
343
+ * (`findVatCategoryViolations`), naming the first rule it breaks; no value is
344
+ * put in place of a missing one.
345
+ * @param accountingDoc The document
346
+ * @param targetFormat The syntax being written
347
+ */
348
+ export const assertVatCategoryWritable = (accountingDoc, targetFormat) => {
349
+ const [violation] = findVatCategoryViolations(accountingDoc, targetFormat);
350
+ if (violation) {
351
+ throw new EInvoiceFormatError(`${violation.ruleId}: ${violation.message}`, {
352
+ targetFormat,
353
+ unsupportedFeatures: [violation.ruleId],
354
+ });
355
+ }
356
+ };
357
+ /**
358
+ * Gives the items of a decoded document the VAT category their lines state
359
+ * (BT-151) and the exemption reason (BT-120) and code (BT-121) of the VAT
360
+ * breakdown they belong to: the one of their category and rate, or of their
361
+ * category for an item not subject to VAT, which states no rate. A line that
362
+ * states no category, or a code EN 16931 does not allow, keeps none; the item
363
+ * is then read as AE or S (`getItemVatCategory`) and the code list rules
364
+ * report the code.
365
+ * @param items The decoded items, in line order
366
+ * @param statedValues What the document states; undefined for a ZUGFeRD 1.0 document
367
+ */
368
+ export const applyStatedVatCategories = (items, statedValues) => {
369
+ if (!statedValues) {
370
+ return;
371
+ }
372
+ items.forEach((item, index) => {
373
+ const category = statedValues.lines[index]?.vatCategoryCode;
374
+ if (!isVatCategoryCode(category)) {
375
+ return;
376
+ }
377
+ item.vatCategory = category;
378
+ const breakdown = statedValues.vatBreakdown.find((group) => group.categoryCode === category && (category === 'O' || group.rate === item.vatPercentage));
379
+ if (breakdown?.exemptionReason) {
380
+ item.vatExemptionReason = breakdown.exemptionReason;
381
+ }
382
+ if (breakdown?.exemptionReasonCode) {
383
+ item.vatExemptionReasonCode = breakdown.exemptionReasonCode;
384
+ }
385
+ });
98
386
  };
99
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmF0LmNhdGVnb3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvZm9ybWF0cy91dGlscy92YXQuY2F0ZWdvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFnQnREOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxhQUEwQyxFQUFvQixFQUFFLENBQzdGLGFBQWEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0FBRTNDOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxDQUFDLFFBQTBCLEVBQUUsUUFBNEIsRUFBNkIsRUFBRSxDQUNySCxRQUFRLEtBQUssSUFBSTtJQUNmLENBQUMsQ0FBQztRQUNFLElBQUksRUFBRSxhQUFhO1FBQ25CLE1BQU0sRUFBRSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQ3JELENBQUMsQ0FBQywrQ0FBK0M7WUFDakQsQ0FBQyxDQUFDLGdCQUFnQjtLQUNyQjtJQUNILENBQUMsQ0FBQyxTQUFTLENBQUM7QUFFaEI7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLENBQUMsSUFBYSxFQUFXLEVBQUUsQ0FBQyxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBUS9IOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZ0NBQWdDLEdBQUcsQ0FDOUMsS0FBMEMsRUFDQyxFQUFFO0lBQzdDLE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDeEYsT0FBTyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxLQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7QUFDdkYsQ0FBQyxDQUFDO0FBRUY7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUNBQW1DLEdBQUcsQ0FBQyxJQUFtQyxFQUFVLEVBQUUsQ0FDakcsMktBQTJLLElBQUksQ0FBQyxLQUFLLHNCQUFzQixNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQywwTkFBME4sQ0FBQztBQUVsYzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFDSCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUFDLGFBQTZCLEVBQUUsWUFBb0IsRUFBUSxFQUFFO0lBQ3JHLE1BQU0sTUFBTSxHQUFHLENBQUMsSUFBWSxFQUFFLE9BQWUsRUFBUyxFQUFFO1FBQ3RELE1BQU0sSUFBSSxtQkFBbUIsQ0FBQyxHQUFHLElBQUksS0FBSyxPQUFPLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN0RyxDQUFDLENBQUM7SUFDRixJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sSUFBSSxHQUFHLGdDQUFnQyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuRSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1QsTUFBTSxDQUFDLFNBQVMsRUFBRSxtQ0FBbUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFDRCxPQUFPO0lBQ1QsQ0FBQztJQUNELEtBQUssTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztRQUNsRSxJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxDQUFDLFVBQVUsRUFBRSxtREFBbUQsS0FBSyxzQkFBc0IsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakksQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsSUFBSSxFQUFFLG1CQUFtQixDQUFDO0lBQ3ZELElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxJQUFJLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sQ0FDSixVQUFVLEVBQ1YsZ1FBQWdRLENBQ2pRLENBQUM7SUFDSixDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLEVBQUUsRUFBRSxtQkFBbUIsQ0FBQztJQUNwRCxJQUFJLENBQUMsS0FBSyxFQUFFLEtBQUssSUFBSSxDQUFDLEtBQUssRUFBRSxjQUFjLEVBQUUsQ0FBQztRQUM1QyxNQUFNLENBQ0osVUFBVSxFQUNWLDBLQUEwSyxDQUMzSyxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQyJ9
387
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmF0LmNhdGVnb3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvZm9ybWF0cy91dGlscy92YXQuY2F0ZWdvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFXdEQsa0ZBQWtGO0FBQ2xGLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFnQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFFOUc7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxLQUFjLEVBQTZCLEVBQUUsQ0FDN0UsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFLLGtCQUF3QyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUV6Rjs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUFnQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztBQVdyRzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUF3QixJQUFJLEdBQUcsQ0FDckQsQ0FDRSw2R0FBNkc7SUFDN0csa0hBQWtIO0lBQ2xILDhHQUE4RztJQUM5RyxtSEFBbUg7SUFDbkgsK0dBQStHO0lBQy9HLHFIQUFxSDtJQUNySCw2R0FBNkc7SUFDN0csc0hBQXNIO0lBQ3RILDRHQUE0RztJQUM1Ryw2R0FBNkc7SUFDN0cscUhBQXFIO0lBQ3JILGtIQUFrSDtJQUNsSCxvRUFBb0UsQ0FDckUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQ2IsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxDQUFDLElBQVksRUFBVyxFQUFFLENB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
@@ -29,16 +29,15 @@ export interface VATBreakdown {
29
29
  * The EN 16931 VAT category rules of a document, checked on the VAT categories
30
30
  * and the VAT breakdown the encoders write.
31
31
  *
32
- * The category of every line is the one the encoders write (`getVatCategory`):
33
- * reverse charge (AE) when the document states `reverseCharge`, standard rated
34
- * (S) otherwise. The envelope states no category of its own for an item or a
35
- * breakdown, so the other categories (Z, E, K, G, O, L, M) cannot occur, and
36
- * an item's `metadata` is not read for one. A decoded document may state one
37
- * for a line (`statedValues.lines[].vatCategoryCode`); the envelope reads such
38
- * a line as S, so BR-S-05 is not reported for a line whose stated category is
39
- * not S. The VAT breakdown is the one the
40
- * encoders write (`computeDocumentTotals().vatGroups`): one group per category
41
- * and rate. The envelope has no document level allowances or charges, so the
32
+ * The category of every line is the one the encoders write
33
+ * (`getItemVatCategory`): the one the item states (`vatCategory`, BT-151),
34
+ * else reverse charge (AE) when the document states `reverseCharge` and
35
+ * standard rated (S) otherwise. A decoded line carries the category its
36
+ * document states. The rules on the items, their exemption reasons and the
37
+ * parties' identifiers are those export refuses a document for
38
+ * (`findVatCategoryViolations`). The VAT breakdown is the one the encoders
39
+ * write (`computeDocumentTotals().vatGroups`): one group per category and
40
+ * rate. The envelope has no document level allowances or charges, so the
42
41
  * rules on them (BR-S-02 to -04 and -06 to -07 and their counterparts) do not
43
42
  * apply, and a taxable amount is the sum of the line net amounts.
44
43
  */
@@ -49,13 +48,13 @@ export declare class VATCategoriesValidator {
49
48
  */
50
49
  validate(invoice: EInvoice): ValidationResult[];
51
50
  /**
52
- * The rules on the lines of each category: the rate (BR-S-05, BR-AE-05), the breakdown the
53
- * category needs (BR-S-01, BR-AE-01) and the parties' identifiers of reverse charge (BR-AE-02)
51
+ * The breakdown a category of the lines needs: at least one for S (BR-S-01), exactly one for
52
+ * reverse charge (BR-AE-01)
54
53
  */
55
- private validateLines;
54
+ private validateBreakdownPresence;
56
55
  /**
57
- * The rules on each VAT breakdown group: its taxable amount (BR-S-08, BR-AE-08), its tax
58
- * amount (BR-S-09, BR-AE-09, BR-CO-17) and its exemption reason (BR-S-10, BR-AE-10)
56
+ * The rules on each VAT breakdown group: its taxable amount (BR-S-08 and its counterparts of
57
+ * every category) and its tax amount (BR-S-09 and its counterparts, BR-CO-17)
59
58
  */
60
59
  private validateBreakdown;
61
60
  private addError;