@fin.cx/einvoice 9.0.0 → 10.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/einvoice.d.ts +12 -0
- package/dist_ts/einvoice.js +45 -3
- package/dist_ts/formats/base/base.decoder.d.ts +27 -2
- package/dist_ts/formats/base/base.decoder.js +52 -27
- package/dist_ts/formats/cii/cii.decoder.d.ts +89 -6
- package/dist_ts/formats/cii/cii.decoder.js +125 -30
- package/dist_ts/formats/cii/cii.encoder.d.ts +71 -1
- package/dist_ts/formats/cii/cii.encoder.js +191 -12
- package/dist_ts/formats/cii/cii.types.d.ts +2 -5
- package/dist_ts/formats/cii/cii.types.js +7 -9
- package/dist_ts/formats/cii/cii.validator.d.ts +13 -6
- package/dist_ts/formats/cii/cii.validator.js +29 -30
- package/dist_ts/formats/cii/facturx/facturx.decoder.js +15 -3
- package/dist_ts/formats/cii/facturx/facturx.encoder.d.ts +0 -6
- package/dist_ts/formats/cii/facturx/facturx.encoder.js +11 -25
- package/dist_ts/formats/cii/facturx/facturx.types.d.ts +0 -5
- package/dist_ts/formats/cii/facturx/facturx.types.js +1 -8
- package/dist_ts/formats/cii/facturx/facturx.validator.d.ts +0 -5
- package/dist_ts/formats/cii/facturx/facturx.validator.js +5 -29
- package/dist_ts/formats/cii/zugferd/zugferd.decoder.js +15 -2
- package/dist_ts/formats/cii/zugferd/zugferd.encoder.d.ts +0 -7
- package/dist_ts/formats/cii/zugferd/zugferd.encoder.js +9 -67
- package/dist_ts/formats/cii/zugferd/zugferd.types.d.ts +0 -5
- package/dist_ts/formats/cii/zugferd/zugferd.types.js +1 -8
- package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.d.ts +26 -0
- package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.js +43 -1
- package/dist_ts/formats/cii/zugferd/zugferd.validator.js +6 -2
- package/dist_ts/formats/semantic/semantic.adapter.js +20 -18
- package/dist_ts/formats/ubl/en16931.ubl.validator.d.ts +0 -4
- package/dist_ts/formats/ubl/en16931.ubl.validator.js +5 -42
- package/dist_ts/formats/ubl/generic/ubl.encoder.js +18 -24
- package/dist_ts/formats/ubl/ubl.decoder.d.ts +4 -0
- package/dist_ts/formats/ubl/ubl.decoder.js +9 -1
- package/dist_ts/formats/ubl/ubl.encoder.js +9 -5
- package/dist_ts/formats/ubl/ubl.validator.d.ts +13 -0
- package/dist_ts/formats/ubl/ubl.validator.js +28 -1
- package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.js +10 -1
- package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.d.ts +0 -7
- package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.js +30 -45
- package/dist_ts/formats/ubl/xrechnung.validator.d.ts +5 -4
- package/dist_ts/formats/ubl/xrechnung.validator.js +71 -68
- package/dist_ts/formats/utils/date.value.d.ts +35 -0
- package/dist_ts/formats/utils/date.value.js +98 -1
- package/dist_ts/formats/utils/format.detector.js +16 -10
- package/dist_ts/formats/utils/party.contact.d.ts +16 -0
- package/dist_ts/formats/utils/party.contact.js +16 -0
- package/dist_ts/formats/utils/party.identifier.d.ts +28 -0
- package/dist_ts/formats/utils/party.identifier.js +49 -0
- package/dist_ts/formats/utils/peppol.profile.d.ts +10 -0
- package/dist_ts/formats/utils/peppol.profile.js +12 -0
- package/dist_ts/formats/utils/seller.identifier.d.ts +46 -0
- package/dist_ts/formats/utils/seller.identifier.js +78 -0
- package/dist_ts/formats/utils/stated.values.d.ts +80 -0
- package/dist_ts/formats/utils/stated.values.js +418 -0
- package/dist_ts/formats/utils/vat.category.d.ts +30 -2
- package/dist_ts/formats/utils/vat.category.js +36 -6
- package/dist_ts/formats/utils/vat.id.d.ts +18 -0
- package/dist_ts/formats/utils/vat.id.js +22 -0
- package/dist_ts/formats/validation/conformance.harness.js +6 -6
- package/dist_ts/formats/validation/en16931.business-rules.validator.js +4 -21
- package/dist_ts/formats/validation/facturx.validator.js +6 -6
- package/dist_ts/formats/validation/integrated.validator.js +4 -13
- package/dist_ts/formats/validation/peppol.validator.js +6 -13
- package/dist_ts/formats/validation/validation.types.d.ts +5 -0
- package/dist_ts/formats/validation/validation.types.js +6 -1
- package/dist_ts/formats/validation/vat-categories.validator.d.ts +21 -42
- package/dist_ts/formats/validation/vat-categories.validator.js +137 -431
- package/dist_ts/formats/validation/xrechnung.validator.d.ts +11 -58
- package/dist_ts/formats/validation/xrechnung.validator.js +58 -324
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +1 -1
- package/dist_ts/interfaces/en16931-metadata.d.ts +0 -4
- package/dist_ts/interfaces/stated.values.d.ts +93 -0
- package/dist_ts/interfaces/stated.values.js +2 -0
- package/package.json +4 -4
- package/readme.md +152 -7
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/einvoice.ts +52 -2
- package/ts/formats/base/base.decoder.ts +55 -45
- package/ts/formats/cii/cii.decoder.ts +159 -32
- package/ts/formats/cii/cii.encoder.ts +206 -14
- package/ts/formats/cii/cii.types.ts +7 -9
- package/ts/formats/cii/cii.validator.ts +30 -32
- package/ts/formats/cii/facturx/facturx.decoder.ts +16 -2
- package/ts/formats/cii/facturx/facturx.encoder.ts +13 -25
- package/ts/formats/cii/facturx/facturx.types.ts +0 -9
- package/ts/formats/cii/facturx/facturx.validator.ts +5 -43
- package/ts/formats/cii/zugferd/zugferd.decoder.ts +16 -1
- package/ts/formats/cii/zugferd/zugferd.encoder.ts +10 -72
- package/ts/formats/cii/zugferd/zugferd.types.ts +0 -9
- package/ts/formats/cii/zugferd/zugferd.v1.decoder.ts +56 -0
- package/ts/formats/cii/zugferd/zugferd.validator.ts +5 -1
- package/ts/formats/semantic/semantic.adapter.ts +19 -17
- package/ts/formats/ubl/en16931.ubl.validator.ts +5 -64
- package/ts/formats/ubl/generic/ubl.encoder.ts +19 -23
- package/ts/formats/ubl/ubl.decoder.ts +12 -0
- package/ts/formats/ubl/ubl.encoder.ts +8 -4
- package/ts/formats/ubl/ubl.validator.ts +29 -0
- package/ts/formats/ubl/xrechnung/xrechnung.decoder.ts +8 -0
- package/ts/formats/ubl/xrechnung/xrechnung.encoder.ts +33 -45
- package/ts/formats/ubl/xrechnung.validator.ts +75 -127
- package/ts/formats/utils/date.value.ts +106 -0
- package/ts/formats/utils/format.detector.ts +15 -9
- package/ts/formats/utils/party.contact.ts +30 -0
- package/ts/formats/utils/party.identifier.ts +61 -0
- package/ts/formats/utils/peppol.profile.ts +13 -0
- package/ts/formats/utils/seller.identifier.ts +102 -0
- package/ts/formats/utils/stated.values.ts +499 -0
- package/ts/formats/utils/vat.category.ts +47 -5
- package/ts/formats/utils/vat.id.ts +24 -0
- package/ts/formats/validation/conformance.harness.ts +5 -5
- package/ts/formats/validation/en16931.business-rules.validator.ts +3 -28
- package/ts/formats/validation/facturx.validator.ts +5 -5
- package/ts/formats/validation/integrated.validator.ts +3 -16
- package/ts/formats/validation/peppol.validator.ts +5 -16
- package/ts/formats/validation/validation.types.ts +7 -1
- package/ts/formats/validation/vat-categories.validator.ts +179 -761
- package/ts/formats/validation/xrechnung.validator.ts +61 -382
- package/ts/index.ts +9 -0
- package/ts/interfaces/en16931-metadata.ts +3 -7
- package/ts/interfaces/stated.values.ts +94 -0
- package/ts/readme.md +1 -1
- package/dist_ts/formats/utils/eu.memberstates.d.ts +0 -11
- package/dist_ts/formats/utils/eu.memberstates.js +0 -16
- package/ts/formats/utils/eu.memberstates.ts +0 -16
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { xpath } from '../../plugins.js';
|
|
2
|
+
import { CII_NAMESPACES } from '../cii/cii.types.js';
|
|
3
|
+
import { UBL_NAMESPACES } from '../ubl/ubl.types.js';
|
|
4
|
+
import { Decimal } from './decimal.js';
|
|
5
|
+
import { toPlainDecimalString } from './number.text.js';
|
|
6
|
+
/** The EN 16931 names of the amounts read, for a message */
|
|
7
|
+
const BUSINESS_TERM_NAMES = {
|
|
8
|
+
'BT-92': 'document level allowance amount',
|
|
9
|
+
'BT-93': 'document level allowance base amount',
|
|
10
|
+
'BT-94': 'document level allowance percentage',
|
|
11
|
+
'BT-96': 'document level allowance VAT rate',
|
|
12
|
+
'BT-99': 'document level charge amount',
|
|
13
|
+
'BT-100': 'document level charge base amount',
|
|
14
|
+
'BT-101': 'document level charge percentage',
|
|
15
|
+
'BT-103': 'document level charge VAT rate',
|
|
16
|
+
'BT-106': 'sum of invoice line net amount',
|
|
17
|
+
'BT-107': 'sum of allowances on document level',
|
|
18
|
+
'BT-108': 'sum of charges on document level',
|
|
19
|
+
'BT-109': 'invoice total amount without VAT',
|
|
20
|
+
'BT-110': 'invoice total VAT amount',
|
|
21
|
+
'BT-111': 'invoice total VAT amount in accounting currency',
|
|
22
|
+
'BT-112': 'invoice total amount with VAT',
|
|
23
|
+
'BT-113': 'paid amount',
|
|
24
|
+
'BT-114': 'rounding amount',
|
|
25
|
+
'BT-115': 'amount due for payment',
|
|
26
|
+
'BT-116': 'VAT category taxable amount',
|
|
27
|
+
'BT-117': 'VAT category tax amount',
|
|
28
|
+
'BT-119': 'VAT category rate',
|
|
29
|
+
'BT-131': 'invoice line net amount',
|
|
30
|
+
'BT-152': 'invoiced item VAT rate',
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The message for a stated amount that is no decimal number, as the paid
|
|
34
|
+
* amount's has been: "The paid amount (BT-113) is no decimal number: …"
|
|
35
|
+
* @param problem The problem
|
|
36
|
+
*/
|
|
37
|
+
export const statedValueProblemMessage = (problem) => `The ${BUSINESS_TERM_NAMES[problem.businessTerm] ?? 'amount'} (${problem.businessTerm}) is no decimal number: ${problem.text}`;
|
|
38
|
+
const nodesOf = (result) => (Array.isArray(result) ? result : []);
|
|
39
|
+
/**
|
|
40
|
+
* Reads the stated values of one document, with an XPath selector for its
|
|
41
|
+
* syntax; an amount whose text is no decimal number is left undefined and
|
|
42
|
+
* listed as a problem
|
|
43
|
+
*/
|
|
44
|
+
class StatedValueReader {
|
|
45
|
+
select;
|
|
46
|
+
doc;
|
|
47
|
+
problems = [];
|
|
48
|
+
constructor(select, doc) {
|
|
49
|
+
this.select = select;
|
|
50
|
+
this.doc = doc;
|
|
51
|
+
}
|
|
52
|
+
nodes(path, context = this.doc) {
|
|
53
|
+
return nodesOf(this.select(path, context));
|
|
54
|
+
}
|
|
55
|
+
text(path, context = this.doc) {
|
|
56
|
+
const [node] = this.nodes(path, context);
|
|
57
|
+
const text = node?.textContent?.trim();
|
|
58
|
+
return text ? text : undefined;
|
|
59
|
+
}
|
|
60
|
+
amount(path, businessTerm, context = this.doc) {
|
|
61
|
+
const text = this.text(path, context);
|
|
62
|
+
if (text === undefined) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
const value = Number(text);
|
|
66
|
+
if (!/^[+-]?(\d+\.?\d*|\.\d+)$/.test(text) || !Number.isFinite(value)) {
|
|
67
|
+
this.problems.push({ businessTerm, text });
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Whether an xs:boolean indicator states the value ('true' or '1', 'false' or '0') */
|
|
74
|
+
const isIndicator = (text, value) => value ? text === 'true' || text === '1' : text === 'false' || text === '0';
|
|
75
|
+
/** Only the fields a document states, so that an absent one is undefined */
|
|
76
|
+
const stated = (fields) => Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));
|
|
77
|
+
const ublSelect = xpath.useNamespaces({ cac: UBL_NAMESPACES.CAC, cbc: UBL_NAMESPACES.CBC });
|
|
78
|
+
/**
|
|
79
|
+
* Reads the stated values of a UBL invoice or credit note: the document totals
|
|
80
|
+
* (`cac:LegalMonetaryTotal`, BT-106 to BT-115, the VAT total `cac:TaxTotal/cbc:TaxAmount`
|
|
81
|
+
* in the document currency for BT-110 and in the VAT accounting currency for
|
|
82
|
+
* BT-111), the VAT breakdown (`cac:TaxSubtotal`, BT-116 to BT-121), the line
|
|
83
|
+
* amounts (BT-126, BT-131, BT-151, BT-152) and the document level allowances
|
|
84
|
+
* and charges (`cac:AllowanceCharge`, BT-92 to BT-105)
|
|
85
|
+
* @param doc The UBL document
|
|
86
|
+
*/
|
|
87
|
+
export const readUblStatedValues = (doc) => {
|
|
88
|
+
const read = new StatedValueReader(ublSelect, doc);
|
|
89
|
+
const total = '/*/cac:LegalMonetaryTotal';
|
|
90
|
+
const documentCurrency = read.text('/*/cbc:DocumentCurrencyCode');
|
|
91
|
+
const accountingCurrency = read.text('/*/cbc:TaxCurrencyCode');
|
|
92
|
+
const taxTotalIn = (currency, businessTerm) => currency === undefined ? undefined : read.amount(`/*/cac:TaxTotal/cbc:TaxAmount[@currencyID = '${currency}']`, businessTerm);
|
|
93
|
+
const accountingTaxTotal = accountingCurrency && accountingCurrency !== documentCurrency ? taxTotalIn(accountingCurrency, 'BT-111') : undefined;
|
|
94
|
+
// BT-110 and the VAT breakdown (BG-23) are the VAT total in the document currency and its subtotals;
|
|
95
|
+
// a second total in the VAT accounting currency (BT-111) may state subtotals of its own
|
|
96
|
+
const documentTaxTotals = read
|
|
97
|
+
.nodes('/*/cac:TaxTotal')
|
|
98
|
+
.filter((taxTotal) => documentCurrency !== undefined && read.text(`./cbc:TaxAmount[@currencyID = '${documentCurrency}']`, taxTotal) !== undefined);
|
|
99
|
+
// a total without a currency, which the UBL schema does not allow, is read as the document's
|
|
100
|
+
const candidateTotals = documentTaxTotals.length > 0 ? documentTaxTotals : read.nodes('/*/cac:TaxTotal');
|
|
101
|
+
const [breakdownTotal] = candidateTotals.filter((taxTotal) => read.nodes('./cac:TaxSubtotal', taxTotal).length > 0);
|
|
102
|
+
const breakdownTaxTotal = breakdownTotal === undefined ? undefined : read.amount('./cbc:TaxAmount', 'BT-110', breakdownTotal);
|
|
103
|
+
const totals = stated({
|
|
104
|
+
lineTotal: read.amount(`${total}/cbc:LineExtensionAmount`, 'BT-106'),
|
|
105
|
+
allowanceTotal: read.amount(`${total}/cbc:AllowanceTotalAmount`, 'BT-107'),
|
|
106
|
+
chargeTotal: read.amount(`${total}/cbc:ChargeTotalAmount`, 'BT-108'),
|
|
107
|
+
taxExclusiveTotal: read.amount(`${total}/cbc:TaxExclusiveAmount`, 'BT-109'),
|
|
108
|
+
taxTotal: breakdownTaxTotal ?? taxTotalIn(documentCurrency, 'BT-110'),
|
|
109
|
+
taxTotalInAccountingCurrency: accountingTaxTotal === undefined || accountingCurrency === undefined ? undefined : { amount: accountingTaxTotal, currency: accountingCurrency },
|
|
110
|
+
taxInclusiveTotal: read.amount(`${total}/cbc:TaxInclusiveAmount`, 'BT-112'),
|
|
111
|
+
paidAmount: read.amount(`${total}/cbc:PrepaidAmount`, 'BT-113'),
|
|
112
|
+
roundingAmount: read.amount(`${total}/cbc:PayableRoundingAmount`, 'BT-114'),
|
|
113
|
+
amountDue: read.amount(`${total}/cbc:PayableAmount`, 'BT-115'),
|
|
114
|
+
});
|
|
115
|
+
const vatBreakdown = (breakdownTotal === undefined ? [] : read.nodes('./cac:TaxSubtotal', breakdownTotal)).map((subtotal) => stated({
|
|
116
|
+
taxableAmount: read.amount('./cbc:TaxableAmount', 'BT-116', subtotal),
|
|
117
|
+
taxAmount: read.amount('./cbc:TaxAmount', 'BT-117', subtotal),
|
|
118
|
+
categoryCode: read.text('./cac:TaxCategory/cbc:ID', subtotal),
|
|
119
|
+
rate: read.amount('./cac:TaxCategory/cbc:Percent', 'BT-119', subtotal),
|
|
120
|
+
exemptionReason: read.text('./cac:TaxCategory/cbc:TaxExemptionReason', subtotal),
|
|
121
|
+
exemptionReasonCode: read.text('./cac:TaxCategory/cbc:TaxExemptionReasonCode', subtotal),
|
|
122
|
+
}));
|
|
123
|
+
const lines = read.nodes('/*/cac:InvoiceLine | /*/cac:CreditNoteLine').map((line) => stated({
|
|
124
|
+
lineId: read.text('./cbc:ID', line),
|
|
125
|
+
netAmount: read.amount('./cbc:LineExtensionAmount', 'BT-131', line),
|
|
126
|
+
vatCategoryCode: read.text('./cac:Item/cac:ClassifiedTaxCategory/cbc:ID', line),
|
|
127
|
+
vatRate: read.amount('./cac:Item/cac:ClassifiedTaxCategory/cbc:Percent', 'BT-152', line),
|
|
128
|
+
}));
|
|
129
|
+
const allowanceCharges = (charge) => read
|
|
130
|
+
.nodes('/*/cac:AllowanceCharge')
|
|
131
|
+
.filter((node) => isIndicator(read.text('./cbc:ChargeIndicator', node), charge))
|
|
132
|
+
.map((node) => stated({
|
|
133
|
+
amount: read.amount('./cbc:Amount', charge ? 'BT-99' : 'BT-92', node),
|
|
134
|
+
baseAmount: read.amount('./cbc:BaseAmount', charge ? 'BT-100' : 'BT-93', node),
|
|
135
|
+
percentage: read.amount('./cbc:MultiplierFactorNumeric', charge ? 'BT-101' : 'BT-94', node),
|
|
136
|
+
vatCategoryCode: read.text('./cac:TaxCategory/cbc:ID', node),
|
|
137
|
+
vatRate: read.amount('./cac:TaxCategory/cbc:Percent', charge ? 'BT-103' : 'BT-96', node),
|
|
138
|
+
reason: read.text('./cbc:AllowanceChargeReason', node),
|
|
139
|
+
reasonCode: read.text('./cbc:AllowanceChargeReasonCode', node),
|
|
140
|
+
}));
|
|
141
|
+
return {
|
|
142
|
+
values: { totals, vatBreakdown, lines, allowances: allowanceCharges(false), charges: allowanceCharges(true) },
|
|
143
|
+
problems: read.problems,
|
|
144
|
+
documentCurrencyTaxTotals: documentCurrency === undefined ? 0 : read.nodes(`/*/cac:TaxTotal/cbc:TaxAmount[@currencyID = '${documentCurrency}']`).length,
|
|
145
|
+
ublTaxTotals: read.nodes('/*/cac:TaxTotal').map((taxTotal) => ({
|
|
146
|
+
taxAmount: read.amount('./cbc:TaxAmount', 'BT-110', taxTotal),
|
|
147
|
+
subtotalTaxAmounts: read.nodes('./cac:TaxSubtotal', taxTotal).map((subtotal) => read.amount('./cbc:TaxAmount', 'BT-117', subtotal)),
|
|
148
|
+
})),
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
const ciiSelect = xpath.useNamespaces({ rsm: CII_NAMESPACES.RSM, ram: CII_NAMESPACES.RAM, udt: CII_NAMESPACES.UDT });
|
|
152
|
+
/**
|
|
153
|
+
* Reads the stated values of a CII (D16B) document: the document totals of the
|
|
154
|
+
* header settlement (`ram:SpecifiedTradeSettlementHeaderMonetarySummation`,
|
|
155
|
+
* BT-106 to BT-115, `ram:TaxTotalAmount` in the invoice currency for BT-110 and
|
|
156
|
+
* in the VAT accounting currency for BT-111), the VAT breakdown (the header
|
|
157
|
+
* `ram:ApplicableTradeTax`, BT-116 to BT-121), the line amounts (BT-126,
|
|
158
|
+
* BT-131, BT-151, BT-152) and the document level allowances and charges (the
|
|
159
|
+
* header `ram:SpecifiedTradeAllowanceCharge`, BT-92 to BT-105)
|
|
160
|
+
* @param doc The CII document
|
|
161
|
+
*/
|
|
162
|
+
export const readCiiStatedValues = (doc) => {
|
|
163
|
+
const read = new StatedValueReader(ciiSelect, doc);
|
|
164
|
+
const settlement = '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement';
|
|
165
|
+
const total = `${settlement}/ram:SpecifiedTradeSettlementHeaderMonetarySummation`;
|
|
166
|
+
const documentCurrency = read.text(`${settlement}/ram:InvoiceCurrencyCode`);
|
|
167
|
+
const accountingCurrency = read.text(`${settlement}/ram:TaxCurrencyCode`);
|
|
168
|
+
// CII tells BT-110 and BT-111 apart by their currency (BR-CO-15 reads BT-110 as the one in the invoice currency)
|
|
169
|
+
const taxTotalIn = (currency, businessTerm) => currency === undefined ? undefined : read.amount(`${total}/ram:TaxTotalAmount[@currencyID = '${currency}']`, businessTerm);
|
|
170
|
+
const accountingTaxTotal = accountingCurrency && accountingCurrency !== documentCurrency ? taxTotalIn(accountingCurrency, 'BT-111') : undefined;
|
|
171
|
+
const totals = stated({
|
|
172
|
+
lineTotal: read.amount(`${total}/ram:LineTotalAmount`, 'BT-106'),
|
|
173
|
+
allowanceTotal: read.amount(`${total}/ram:AllowanceTotalAmount`, 'BT-107'),
|
|
174
|
+
chargeTotal: read.amount(`${total}/ram:ChargeTotalAmount`, 'BT-108'),
|
|
175
|
+
taxExclusiveTotal: read.amount(`${total}/ram:TaxBasisTotalAmount`, 'BT-109'),
|
|
176
|
+
taxTotal: taxTotalIn(documentCurrency, 'BT-110'),
|
|
177
|
+
taxTotalInAccountingCurrency: accountingTaxTotal === undefined || accountingCurrency === undefined ? undefined : { amount: accountingTaxTotal, currency: accountingCurrency },
|
|
178
|
+
taxInclusiveTotal: read.amount(`${total}/ram:GrandTotalAmount`, 'BT-112'),
|
|
179
|
+
paidAmount: read.amount(`${total}/ram:TotalPrepaidAmount`, 'BT-113'),
|
|
180
|
+
roundingAmount: read.amount(`${total}/ram:RoundingAmount`, 'BT-114'),
|
|
181
|
+
amountDue: read.amount(`${total}/ram:DuePayableAmount`, 'BT-115'),
|
|
182
|
+
});
|
|
183
|
+
const vatBreakdown = read.nodes(`${settlement}/ram:ApplicableTradeTax`).map((tax) => stated({
|
|
184
|
+
taxableAmount: read.amount('./ram:BasisAmount', 'BT-116', tax),
|
|
185
|
+
taxAmount: read.amount('./ram:CalculatedAmount', 'BT-117', tax),
|
|
186
|
+
categoryCode: read.text('./ram:CategoryCode', tax),
|
|
187
|
+
rate: read.amount('./ram:RateApplicablePercent', 'BT-119', tax),
|
|
188
|
+
exemptionReason: read.text('./ram:ExemptionReason', tax),
|
|
189
|
+
exemptionReasonCode: read.text('./ram:ExemptionReasonCode', tax),
|
|
190
|
+
}));
|
|
191
|
+
const lines = read.nodes('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:IncludedSupplyChainTradeLineItem').map((line) => stated({
|
|
192
|
+
lineId: read.text('./ram:AssociatedDocumentLineDocument/ram:LineID', line),
|
|
193
|
+
netAmount: read.amount('./ram:SpecifiedLineTradeSettlement/ram:SpecifiedTradeSettlementLineMonetarySummation/ram:LineTotalAmount', 'BT-131', line),
|
|
194
|
+
vatCategoryCode: read.text('./ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:CategoryCode', line),
|
|
195
|
+
vatRate: read.amount('./ram:SpecifiedLineTradeSettlement/ram:ApplicableTradeTax/ram:RateApplicablePercent', 'BT-152', line),
|
|
196
|
+
}));
|
|
197
|
+
const allowanceCharges = (charge) => read
|
|
198
|
+
.nodes(`${settlement}/ram:SpecifiedTradeAllowanceCharge`)
|
|
199
|
+
.filter((node) => isIndicator(read.text('./ram:ChargeIndicator/udt:Indicator', node), charge))
|
|
200
|
+
.map((node) => stated({
|
|
201
|
+
amount: read.amount('./ram:ActualAmount', charge ? 'BT-99' : 'BT-92', node),
|
|
202
|
+
baseAmount: read.amount('./ram:BasisAmount', charge ? 'BT-100' : 'BT-93', node),
|
|
203
|
+
percentage: read.amount('./ram:CalculationPercent', charge ? 'BT-101' : 'BT-94', node),
|
|
204
|
+
vatCategoryCode: read.text('./ram:CategoryTradeTax/ram:CategoryCode', node),
|
|
205
|
+
vatRate: read.amount('./ram:CategoryTradeTax/ram:RateApplicablePercent', charge ? 'BT-103' : 'BT-96', node),
|
|
206
|
+
reason: read.text('./ram:Reason', node),
|
|
207
|
+
reasonCode: read.text('./ram:ReasonCode', node),
|
|
208
|
+
}));
|
|
209
|
+
return {
|
|
210
|
+
values: { totals, vatBreakdown, lines, allowances: allowanceCharges(false), charges: allowanceCharges(true) },
|
|
211
|
+
problems: read.problems,
|
|
212
|
+
documentCurrencyTaxTotals: documentCurrency === undefined ? 0 : read.nodes(`${total}/ram:TaxTotalAmount[@currencyID = '${documentCurrency}']`).length,
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
/** The official texts of the EN 16931 rules on the document totals (CEN artefacts 1.3.16) */
|
|
216
|
+
const TOTALS_RULES = {
|
|
217
|
+
'BR-CO-10': 'Sum of Invoice line net amount (BT-106) = Σ Invoice line net amount (BT-131).',
|
|
218
|
+
'BR-CO-11': 'Sum of allowances on document level (BT-107) = Σ Document level allowance amount (BT-92).',
|
|
219
|
+
'BR-CO-12': 'Sum of charges on document level (BT-108) = Σ Document level charge amount (BT-99).',
|
|
220
|
+
'BR-CO-13': 'Invoice total amount without VAT (BT-109) = Σ Invoice line net amount (BT-131) - Sum of allowances on document level (BT-107) + Sum of charges on document level (BT-108).',
|
|
221
|
+
'BR-CO-14': 'Invoice total VAT amount (BT-110) = Σ VAT category tax amount (BT-117).',
|
|
222
|
+
'BR-CO-15': 'Invoice total amount with VAT (BT-112) = Invoice total amount without VAT (BT-109) + Invoice total VAT amount (BT-110).',
|
|
223
|
+
'BR-CO-16': 'Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) -Paid amount (BT-113) +Rounding amount (BT-114).',
|
|
224
|
+
'BR-CO-17': 'VAT category tax amount (BT-117) = VAT category taxable amount (BT-116) x (VAT category rate (BT-119) / 100), rounded to two decimals.',
|
|
225
|
+
};
|
|
226
|
+
const decimal = (value) => new Decimal(toPlainDecimalString(value));
|
|
227
|
+
const sum = (values) => Decimal.sum(values.map((value) => decimal(value ?? 0)));
|
|
228
|
+
/** XPath's round(x × 100) div 100: two decimals, a half rounded towards positive infinity */
|
|
229
|
+
const roundCents = (value) => value.multiply(100).add('0.5').round(0, 'FLOOR').divide(100);
|
|
230
|
+
/** XPath's round(x): an integer, a half rounded towards positive infinity */
|
|
231
|
+
const roundInteger = (value) => value.add('0.5').round(0, 'FLOOR');
|
|
232
|
+
/**
|
|
233
|
+
* Checks the stated values of a document against each other as the EN 16931
|
|
234
|
+
* rules BR-CO-10 to BR-CO-17 do in the CEN artefacts 1.3.16: each sum rounded
|
|
235
|
+
* to two decimals, BR-CO-17 with the artefacts' tolerance of one unit (UBL
|
|
236
|
+
* strictly within it, CII up to it). A rule whose amounts the document does
|
|
237
|
+
* not state is not checked; the rules on the presence of the totals (BR-12 to
|
|
238
|
+
* BR-15) report that.
|
|
239
|
+
* @param read The stated values read from the document
|
|
240
|
+
* @param syntax The document's syntax
|
|
241
|
+
*/
|
|
242
|
+
export const findStatedValueDisagreements = (read, syntax) => {
|
|
243
|
+
const { values } = read;
|
|
244
|
+
const locations = syntax === 'ubl' ? UBL_TOTALS_LOCATIONS : CII_TOTALS_LOCATIONS;
|
|
245
|
+
const findings = [];
|
|
246
|
+
const report = (ruleId, detail) => findings.push({ ruleId, message: `${TOTALS_RULES[ruleId]} ${detail}`, location: locations[ruleId] });
|
|
247
|
+
const { totals } = values;
|
|
248
|
+
const text = (value) => value.toString(2);
|
|
249
|
+
if (totals.lineTotal !== undefined) {
|
|
250
|
+
const expected = roundCents(sum(values.lines.map((line) => line.netAmount)));
|
|
251
|
+
if (!decimal(totals.lineTotal).equals(expected)) {
|
|
252
|
+
report('BR-CO-10', `The document states ${totals.lineTotal}, the sum of its line net amounts is ${text(expected)}.`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const checkSum = (ruleId, stated, entries) => {
|
|
256
|
+
if (stated === undefined && entries.length === 0) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const expected = roundCents(sum(entries.map((entry) => entry.amount)));
|
|
260
|
+
if (stated === undefined || !decimal(stated).equals(expected)) {
|
|
261
|
+
report(ruleId, `The document states ${stated ?? 'none'}, the sum of its amounts is ${text(expected)}.`);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
checkSum('BR-CO-11', totals.allowanceTotal, values.allowances);
|
|
265
|
+
checkSum('BR-CO-12', totals.chargeTotal, values.charges);
|
|
266
|
+
if (totals.taxExclusiveTotal !== undefined && totals.lineTotal !== undefined) {
|
|
267
|
+
const expected = roundCents(decimal(totals.lineTotal).subtract(totals.allowanceTotal ?? 0).add(totals.chargeTotal ?? 0));
|
|
268
|
+
if (!decimal(totals.taxExclusiveTotal).equals(expected)) {
|
|
269
|
+
report('BR-CO-13', `The document states ${totals.taxExclusiveTotal}, BT-106 - BT-107 + BT-108 is ${text(expected)}.`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (syntax === 'ubl') {
|
|
273
|
+
// each VAT total with subtotals, on its own, as the UBL artefacts check it
|
|
274
|
+
(read.ublTaxTotals ?? []).forEach((taxTotal) => {
|
|
275
|
+
if (taxTotal.subtotalTaxAmounts.length === 0) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const expected = roundCents(sum(taxTotal.subtotalTaxAmounts));
|
|
279
|
+
if (taxTotal.taxAmount === undefined || !decimal(taxTotal.taxAmount).equals(expected)) {
|
|
280
|
+
report('BR-CO-14', `A VAT total states ${taxTotal.taxAmount ?? 'none'}, the sum of its VAT category tax amounts is ${text(expected)}.`);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
else if (totals.taxTotal !== undefined) {
|
|
285
|
+
// the VAT total in the invoice currency against every header VAT breakdown
|
|
286
|
+
const expected = roundCents(sum(values.vatBreakdown.map((group) => group.taxAmount)));
|
|
287
|
+
if (!decimal(totals.taxTotal).equals(expected)) {
|
|
288
|
+
report('BR-CO-14', `The document states ${totals.taxTotal}, the sum of its VAT category tax amounts is ${text(expected)}.`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (totals.taxInclusiveTotal !== undefined && totals.taxExclusiveTotal !== undefined) {
|
|
292
|
+
const inclusive = decimal(totals.taxInclusiveTotal);
|
|
293
|
+
const exclusive = decimal(totals.taxExclusiveTotal);
|
|
294
|
+
const withTax = totals.taxTotal === undefined ? undefined : roundCents(exclusive.add(totals.taxTotal));
|
|
295
|
+
// both ask for exactly one VAT total in the document currency; CII also accepts a total with VAT equal to the one without
|
|
296
|
+
const agrees = syntax === 'ubl'
|
|
297
|
+
? read.documentCurrencyTaxTotals === 1 && withTax !== undefined && inclusive.equals(withTax)
|
|
298
|
+
: (read.documentCurrencyTaxTotals === 1 && withTax !== undefined && inclusive.equals(withTax)) || inclusive.equals(exclusive);
|
|
299
|
+
if (!agrees) {
|
|
300
|
+
report('BR-CO-15', `The document states ${totals.taxInclusiveTotal}, BT-109 + BT-110 is ${withTax === undefined ? 'not stated' : text(withTax)}.`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (totals.amountDue !== undefined && totals.taxInclusiveTotal !== undefined) {
|
|
304
|
+
const expected = decimal(totals.taxInclusiveTotal).subtract(totals.paidAmount ?? 0).add(totals.roundingAmount ?? 0);
|
|
305
|
+
// UBL compares both sides rounded to two decimals, CII the stated amounts as they are
|
|
306
|
+
const agrees = syntax === 'ubl'
|
|
307
|
+
? roundCents(decimal(totals.amountDue).subtract(totals.roundingAmount ?? 0)).equals(roundCents(decimal(totals.taxInclusiveTotal).subtract(totals.paidAmount ?? 0)))
|
|
308
|
+
: decimal(totals.amountDue).equals(expected);
|
|
309
|
+
if (!agrees) {
|
|
310
|
+
report('BR-CO-16', `The document states ${totals.amountDue}, BT-112 - BT-113 + BT-114 is ${text(expected)}.`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
values.vatBreakdown.forEach((group, index) => {
|
|
314
|
+
if (group.taxAmount === undefined) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const taxAmount = decimal(group.taxAmount);
|
|
318
|
+
const rate = group.rate === undefined ? undefined : decimal(group.rate);
|
|
319
|
+
let agrees;
|
|
320
|
+
if (rate === undefined || roundInteger(rate).isZero()) {
|
|
321
|
+
agrees = roundInteger(taxAmount).isZero();
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
const expected = roundCents(decimal(group.taxableAmount ?? 0).abs().multiply(rate.divide(100)));
|
|
325
|
+
// the artefacts accept a tax amount within one unit of the computed one
|
|
326
|
+
agrees =
|
|
327
|
+
syntax === 'ubl'
|
|
328
|
+
? taxAmount.abs().subtract(1).lessThan(expected) && taxAmount.abs().add(1).greaterThan(expected)
|
|
329
|
+
: taxAmount.abs().subtract(1).lessThanOrEqual(expected) && taxAmount.abs().add(1).greaterThanOrEqual(expected);
|
|
330
|
+
}
|
|
331
|
+
if (!agrees) {
|
|
332
|
+
findings.push({
|
|
333
|
+
ruleId: 'BR-CO-17',
|
|
334
|
+
message: `${TOTALS_RULES['BR-CO-17']} VAT breakdown ${index + 1} (${group.categoryCode ?? '?'} ${group.rate ?? ''}) states ${group.taxAmount} on ${group.taxableAmount ?? 'no taxable amount'}.`,
|
|
335
|
+
location: locations['BR-CO-17'],
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
return findings;
|
|
340
|
+
};
|
|
341
|
+
/** Where the rules on the totals apply in a UBL document */
|
|
342
|
+
const UBL_TOTALS_LOCATIONS = {
|
|
343
|
+
'BR-CO-10': '/*/cac:LegalMonetaryTotal/cbc:LineExtensionAmount',
|
|
344
|
+
'BR-CO-11': '/*/cac:LegalMonetaryTotal/cbc:AllowanceTotalAmount',
|
|
345
|
+
'BR-CO-12': '/*/cac:LegalMonetaryTotal/cbc:ChargeTotalAmount',
|
|
346
|
+
'BR-CO-13': '/*/cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount',
|
|
347
|
+
'BR-CO-14': '/*/cac:TaxTotal/cbc:TaxAmount',
|
|
348
|
+
'BR-CO-15': '/*/cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount',
|
|
349
|
+
'BR-CO-16': '/*/cac:LegalMonetaryTotal/cbc:PayableAmount',
|
|
350
|
+
'BR-CO-17': '/*/cac:TaxTotal/cac:TaxSubtotal',
|
|
351
|
+
};
|
|
352
|
+
const CII_TOTALS = '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementHeaderMonetarySummation';
|
|
353
|
+
/** Where the rules on the totals apply in a CII document */
|
|
354
|
+
const CII_TOTALS_LOCATIONS = {
|
|
355
|
+
'BR-CO-10': `${CII_TOTALS}/ram:LineTotalAmount`,
|
|
356
|
+
'BR-CO-11': `${CII_TOTALS}/ram:AllowanceTotalAmount`,
|
|
357
|
+
'BR-CO-12': `${CII_TOTALS}/ram:ChargeTotalAmount`,
|
|
358
|
+
'BR-CO-13': `${CII_TOTALS}/ram:TaxBasisTotalAmount`,
|
|
359
|
+
'BR-CO-14': `${CII_TOTALS}/ram:TaxTotalAmount`,
|
|
360
|
+
'BR-CO-15': `${CII_TOTALS}/ram:GrandTotalAmount`,
|
|
361
|
+
'BR-CO-16': `${CII_TOTALS}/ram:DuePayableAmount`,
|
|
362
|
+
'BR-CO-17': '/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax',
|
|
363
|
+
};
|
|
364
|
+
/** The package's code for a stated value the envelope computes differently */
|
|
365
|
+
export const STATED_VALUE_DIFFERS_CODE = 'EINVOICE-STATED-DIFFERS';
|
|
366
|
+
/**
|
|
367
|
+
* The stated values of a loaded document that the envelope's computation
|
|
368
|
+
* (`computeDocumentTotals`, what `totalNet`, `totalVat`, `totalGross` and the
|
|
369
|
+
* encoders give) does not reproduce: the totals BT-106, BT-109, BT-110,
|
|
370
|
+
* BT-112 and BT-115, each line's net amount (BT-131) and VAT category
|
|
371
|
+
* (BT-151), and each VAT breakdown's category, rate and amounts (BG-23). No
|
|
372
|
+
* EN 16931 rule is broken by such a difference, so it is the package's own
|
|
373
|
+
* finding: the envelope has no document or line allowances and charges and no
|
|
374
|
+
* price base quantity, and every line is standard rated or reverse charge.
|
|
375
|
+
* Neither value is changed.
|
|
376
|
+
* @param values The stated values
|
|
377
|
+
* @param totals The envelope's computation
|
|
378
|
+
* @param paidAmount The envelope's paid amount (BT-113)
|
|
379
|
+
*/
|
|
380
|
+
export const findEnvelopeDifferences = (values, totals, paidAmount) => {
|
|
381
|
+
const findings = [];
|
|
382
|
+
const differs = (businessTerm, field, stated, computed) => findings.push({
|
|
383
|
+
ruleId: STATED_VALUE_DIFFERS_CODE,
|
|
384
|
+
message: `The document states ${businessTerm} ${stated}; the envelope computes ${computed}. The stated value is statedValues.${field}; the envelope cannot express document or line allowances and charges (BG-20, BG-21, BG-27, BG-28), a price base quantity (BT-149) or a VAT category other than S and AE, and neither value is changed.`,
|
|
385
|
+
location: `statedValues.${field}`,
|
|
386
|
+
});
|
|
387
|
+
const compareAmount = (businessTerm, field, stated, computed) => {
|
|
388
|
+
if (stated !== undefined && !decimal(stated).equals(computed)) {
|
|
389
|
+
differs(businessTerm, field, stated, computed.toString(totals.minorUnits));
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
compareAmount('BT-106', 'totals.lineTotal', values.totals.lineTotal, totals.lineTotal);
|
|
393
|
+
compareAmount('BT-109', 'totals.taxExclusiveTotal', values.totals.taxExclusiveTotal, totals.taxBasisTotal);
|
|
394
|
+
compareAmount('BT-110', 'totals.taxTotal', values.totals.taxTotal, totals.taxTotal);
|
|
395
|
+
compareAmount('BT-112', 'totals.taxInclusiveTotal', values.totals.taxInclusiveTotal, totals.grandTotal);
|
|
396
|
+
compareAmount('BT-115', 'totals.amountDue', values.totals.amountDue, totals.grandTotal.subtract(paidAmount ?? 0));
|
|
397
|
+
values.lines.forEach((line, index) => {
|
|
398
|
+
const computed = totals.lineNetAmounts[index];
|
|
399
|
+
if (computed !== undefined) {
|
|
400
|
+
compareAmount('BT-131', `lines[${index}].netAmount`, line.netAmount, computed);
|
|
401
|
+
}
|
|
402
|
+
const category = totals.lineVatCategories[index];
|
|
403
|
+
if (line.vatCategoryCode !== undefined && category !== undefined && line.vatCategoryCode !== category) {
|
|
404
|
+
differs('BT-151', `lines[${index}].vatCategoryCode`, line.vatCategoryCode, category);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
values.vatBreakdown.forEach((group, index) => {
|
|
408
|
+
const computed = totals.vatGroups.find((candidate) => candidate.category === group.categoryCode && group.rate !== undefined && decimal(candidate.rate).equals(decimal(group.rate)));
|
|
409
|
+
if (!computed) {
|
|
410
|
+
differs('BG-23', `vatBreakdown[${index}]`, `${group.categoryCode ?? '?'} ${group.rate ?? ''}`.trim(), 'no breakdown of that category and rate');
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
compareAmount('BT-116', `vatBreakdown[${index}].taxableAmount`, group.taxableAmount, computed.taxableAmount);
|
|
414
|
+
compareAmount('BT-117', `vatBreakdown[${index}].taxAmount`, group.taxAmount, computed.taxAmount);
|
|
415
|
+
});
|
|
416
|
+
return findings;
|
|
417
|
+
};
|
|
418
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGVkLnZhbHVlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2Zvcm1hdHMvdXRpbHMvc3RhdGVkLnZhbHVlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFPQSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXZDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBUXhELDREQUE0RDtBQUM1RCxNQUFNLG1CQUFtQixHQUEyQjtJQUNsRCxPQUFPLEVBQUUsaUNBQWlDO0lBQzFDLE9BQU8sRUFBRSxzQ0FBc0M7SUFDL0MsT0FBTyxFQUFFLHFDQUFxQztJQUM5QyxPQUFPLEVBQUUsbUNBQW1DO0lBQzVDLE9BQU8sRUFBRSw4QkFBOEI7SUFDdkMsUUFBUSxFQUFFLG1DQUFtQztJQUM3QyxRQUFRLEVBQUUsa0NBQWtDO0lBQzVDLFFBQVEsRUFBRSxnQ0FBZ0M7SUFDMUMsUUFBUSxFQUFFLGdDQUFnQztJQUMxQyxRQUFRLEVBQUUscUNBQXFDO0lBQy9DLFFBQVEsRUFBRSxrQ0FBa0M7SUFDNUMsUUFBUSxFQUFFLGtDQUFrQztJQUM1QyxRQUFRLEVBQUUsMEJBQTBCO0lBQ3BDLFFBQVEsRUFBRSxpREFBaUQ7SUFDM0QsUUFBUSxFQUFFLCtCQUErQjtJQUN6QyxRQUFRLEVBQUUsYUFBYTtJQUN2QixRQUFRLEVBQUUsaUJBQWlCO0lBQzNCLFFBQVEsRUFBRSx3QkFBd0I7SUFDbEMsUUFBUSxFQUFFLDZCQUE2QjtJQUN2QyxRQUFRLEVBQUUseUJBQXlCO0lBQ25DLFFBQVEsRUFBRSxtQkFBbUI7SUFDN0IsUUFBUSxFQUFFLHlCQUF5QjtJQUNuQyxRQUFR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
|
|
@@ -31,8 +31,36 @@ export declare const getVatCategory: (accountingDoc: {
|
|
|
31
31
|
*/
|
|
32
32
|
export declare const getVatExemption: (category: TVatCategoryCode, language: string | undefined) => IVatExemption | undefined;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* Whether a VAT rate is a number not greater than zero; a rate that is no
|
|
35
|
+
* number is refused as such (`findInvalidItemAmounts`), not as BR-S-05
|
|
36
|
+
* @param rate The rate
|
|
37
|
+
*/
|
|
38
|
+
export declare const isRateNotAboveZero: (rate: unknown) => boolean;
|
|
39
|
+
/** A line written as standard rated (S) whose VAT rate is not greater than zero */
|
|
40
|
+
export interface IStandardRatedLineWithoutRate {
|
|
41
|
+
index: number;
|
|
42
|
+
vatPercentage: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The first line of a document that is not reverse charge whose VAT rate is not
|
|
46
|
+
* greater than zero. The encoders write every such line as standard rated (S),
|
|
47
|
+
* and EN 16931 BR-S-05 asks a standard rated line for a rate greater than zero;
|
|
48
|
+
* the category the line has (zero rated Z, exempt E, intra-community supply K,
|
|
49
|
+
* export G, not subject to VAT O) cannot be stated until an item carries a VAT
|
|
50
|
+
* category of its own.
|
|
51
|
+
* @param items The document's items
|
|
52
|
+
*/
|
|
53
|
+
export declare const findStandardRatedLineWithoutRate: (items: TAccountingDoc["items"] | undefined) => IStandardRatedLineWithoutRate | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* The refusal or finding for such a line
|
|
56
|
+
* @param line The line
|
|
57
|
+
*/
|
|
58
|
+
export declare const standardRatedLineWithoutRateMessage: (line: IStandardRatedLineWithoutRate) => string;
|
|
59
|
+
/**
|
|
60
|
+
* Refuses a document whose lines cannot be written with a valid VAT category,
|
|
61
|
+
* naming the rule: a line outside reverse charge whose rate is not greater than
|
|
62
|
+
* zero (BR-S-05), and a reverse charge document that lacks what EN 16931
|
|
63
|
+
* requires of one; no value is put in place of a missing one.
|
|
36
64
|
* - BR-AE-05: every line of a reverse charge document has the VAT rate 0; the
|
|
37
65
|
* recipient owes the tax, and the invoice states none (§ 14a Abs. 5 Satz 2
|
|
38
66
|
* UStG; a stated amount would be owed under § 14c Abs. 1 UStG).
|
|
@@ -24,8 +24,34 @@ export const getVatExemption = (category, language) => category === 'AE'
|
|
|
24
24
|
}
|
|
25
25
|
: undefined;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* Whether a VAT rate is a number not greater than zero; a rate that is no
|
|
28
|
+
* number is refused as such (`findInvalidItemAmounts`), not as BR-S-05
|
|
29
|
+
* @param rate The rate
|
|
30
|
+
*/
|
|
31
|
+
export const isRateNotAboveZero = (rate) => typeof rate === 'number' && Number.isFinite(rate) && !(rate > 0);
|
|
32
|
+
/**
|
|
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
|
|
40
|
+
*/
|
|
41
|
+
export const findStandardRatedLineWithoutRate = (items) => {
|
|
42
|
+
const index = (items ?? []).findIndex((item) => isRateNotAboveZero(item.vatPercentage));
|
|
43
|
+
return index < 0 ? undefined : { index, vatPercentage: items[index].vatPercentage };
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* The refusal or finding for such a line
|
|
47
|
+
* @param line The line
|
|
48
|
+
*/
|
|
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`;
|
|
50
|
+
/**
|
|
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.
|
|
29
55
|
* - BR-AE-05: every line of a reverse charge document has the VAT rate 0; the
|
|
30
56
|
* recipient owes the tax, and the invoice states none (§ 14a Abs. 5 Satz 2
|
|
31
57
|
* UStG; a stated amount would be owed under § 14c Abs. 1 UStG).
|
|
@@ -46,12 +72,16 @@ export const getVatExemption = (category, language) => category === 'AE'
|
|
|
46
72
|
* @param targetFormat The format being written
|
|
47
73
|
*/
|
|
48
74
|
export const assertVatCategoryWritable = (accountingDoc, targetFormat) => {
|
|
49
|
-
if (!accountingDoc.reverseCharge) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
75
|
const refuse = (rule, message) => {
|
|
53
76
|
throw new EInvoiceFormatError(`${rule}: ${message}`, { targetFormat, unsupportedFeatures: [rule] });
|
|
54
77
|
};
|
|
78
|
+
if (!accountingDoc.reverseCharge) {
|
|
79
|
+
const line = findStandardRatedLineWithoutRate(accountingDoc.items);
|
|
80
|
+
if (line) {
|
|
81
|
+
refuse('BR-S-05', standardRatedLineWithoutRateMessage(line));
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
55
85
|
for (const [index, item] of (accountingDoc.items ?? []).entries()) {
|
|
56
86
|
if (item.vatPercentage !== 0) {
|
|
57
87
|
refuse('BR-AE-05', `a reverse charge line has the VAT rate 0, items[${index}].vatPercentage is ${String(item.vatPercentage)}`);
|
|
@@ -66,4 +96,4 @@ export const assertVatCategoryWritable = (accountingDoc, targetFormat) => {
|
|
|
66
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');
|
|
67
97
|
}
|
|
68
98
|
};
|
|
69
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
99
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmF0LmNhdGVnb3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvZm9ybWF0cy91dGlscy92YXQuY2F0ZWdvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFnQnREOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxhQUEwQyxFQUFvQixFQUFFLENBQzdGLGFBQWEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0FBRTNDOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxDQUFDLFFBQTBCLEVBQUUsUUFBNEIsRUFBNkIsRUFBRSxDQUNySCxRQUFRLEtBQUssSUFBSTtJQUNmLENBQUMsQ0FBQztRQUNFLElBQUksRUFBRSxhQUFhO1FBQ25CLE1BQU0sRUFBRSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQ3JELENBQUMsQ0FBQywrQ0FBK0M7WUFDakQsQ0FBQyxDQUFDLGdCQUFnQjtLQUNyQjtJQUNILENBQUMsQ0FBQyxTQUFTLENBQUM7QUFFaEI7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLENBQUMsSUFBYSxFQUFXLEVBQUUsQ0FBQyxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBUS9IOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZ0NBQWdDLEdBQUcsQ0FDOUMsS0FBMEMsRUFDQyxFQUFFO0lBQzdDLE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDeEYsT0FBTyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxLQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7QUFDdkYsQ0FBQyxDQUFDO0FBRUY7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUNBQW1DLEdBQUcsQ0FBQyxJQUFtQyxFQUFVLEVBQUUsQ0FDakcsMktBQTJLLElBQUksQ0FBQyxLQUFLLHNCQUFzQixNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQywwTkFBME4sQ0FBQztBQUVsYzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFDSCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUFDLGFBQTZCLEVBQUUsWUFBb0IsRUFBUSxFQUFFO0lBQ3JHLE1BQU0sTUFBTSxHQUFHLENBQUMsSUFBWSxFQUFFLE9BQWUsRUFBUyxFQUFFO1FBQ3RELE1BQU0sSUFBSSxtQkFBbUIsQ0FBQyxHQUFHLElBQUksS0FBSyxPQUFPLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN0RyxDQUFDLENBQUM7SUFDRixJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sSUFBSSxHQUFHLGdDQUFnQyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuRSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1QsTUFBTSxDQUFDLFNBQVMsRUFBRSxtQ0FBbUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFDRCxPQUFPO0lBQ1QsQ0FBQztJQUNELEtBQUssTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztRQUNsRSxJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxDQUFDLFVBQVUsRUFBRSxtREFBbUQsS0FBSyxzQkFBc0IsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakksQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsSUFBSSxFQUFFLG1CQUFtQixDQUFDO0lBQ3ZELElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxJQUFJLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sQ0FDSixVQUFVLEVBQ1YsZ1FBQWdRLENBQ2pRLENBQUM7SUFDSixDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLEVBQUUsRUFBRSxtQkFBbUIsQ0FBQztJQUNwRCxJQUFJLENBQUMsS0FBSyxFQUFFLEtBQUssSUFBSSxDQUFDLEtBQUssRUFBRSxjQUFjLEVBQUUsQ0FBQztRQUM1QyxNQUFNLENBQ0osVUFBVSxFQUNWLDBLQUEwSyxDQUMzSyxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQyJ9
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The code of the package's own check of the German VAT identification number format. It is no
|
|
3
|
+
* rule of EN 16931 or XRechnung; the official rules do not check the format of BT-31.
|
|
4
|
+
*/
|
|
5
|
+
export declare const GERMAN_VAT_ID_FORMAT_CODE = "EINVOICE-DE-VATID-FORMAT";
|
|
6
|
+
/**
|
|
7
|
+
* The message of a German VAT identification number whose format is not the one the
|
|
8
|
+
* Bundeszentralamt für Steuern issues (§ 27a Abs. 1 UStG names it as the issuer, not the format)
|
|
9
|
+
* @param vatId The VAT identification number as stated
|
|
10
|
+
*/
|
|
11
|
+
export declare const germanVatIdFormatMessage: (vatId: string) => string;
|
|
12
|
+
/**
|
|
13
|
+
* Whether a VAT identification number with the German prefix DE lacks the format the
|
|
14
|
+
* Bundeszentralamt für Steuern issues, DE followed by nine digits. A number with another prefix, or
|
|
15
|
+
* none, is not checked. The number is taken as it is written, without removing spaces.
|
|
16
|
+
* @param vatId The VAT identification number as stated
|
|
17
|
+
*/
|
|
18
|
+
export declare const isMalformedGermanVatId: (vatId: string | undefined) => boolean;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The code of the package's own check of the German VAT identification number format. It is no
|
|
3
|
+
* rule of EN 16931 or XRechnung; the official rules do not check the format of BT-31.
|
|
4
|
+
*/
|
|
5
|
+
export const GERMAN_VAT_ID_FORMAT_CODE = 'EINVOICE-DE-VATID-FORMAT';
|
|
6
|
+
/**
|
|
7
|
+
* The message of a German VAT identification number whose format is not the one the
|
|
8
|
+
* Bundeszentralamt für Steuern issues (§ 27a Abs. 1 UStG names it as the issuer, not the format)
|
|
9
|
+
* @param vatId The VAT identification number as stated
|
|
10
|
+
*/
|
|
11
|
+
export const germanVatIdFormatMessage = (vatId) => `The German VAT identification number (BT-31) is DE followed by nine digits, the format the Bundeszentralamt für Steuern issues; it is "${vatId}"`;
|
|
12
|
+
/**
|
|
13
|
+
* Whether a VAT identification number with the German prefix DE lacks the format the
|
|
14
|
+
* Bundeszentralamt für Steuern issues, DE followed by nine digits. A number with another prefix, or
|
|
15
|
+
* none, is not checked. The number is taken as it is written, without removing spaces.
|
|
16
|
+
* @param vatId The VAT identification number as stated
|
|
17
|
+
*/
|
|
18
|
+
export const isMalformedGermanVatId = (vatId) => {
|
|
19
|
+
const value = (vatId ?? '').trim();
|
|
20
|
+
return value.startsWith('DE') && !/^DE[0-9]{9}$/.test(value);
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmF0LmlkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvZm9ybWF0cy91dGlscy92YXQuaWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsMEJBQTBCLENBQUM7QUFFcEU7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLENBQUMsS0FBYSxFQUFVLEVBQUUsQ0FDaEUsMElBQTBJLEtBQUssR0FBRyxDQUFDO0FBRXJKOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxLQUF5QixFQUFXLEVBQUU7SUFDM0UsTUFBTSxLQUFLLEdBQUcsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDbkMsT0FBTyxLQUFLLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMvRCxDQUFDLENBQUMifQ==
|