@stackforge-eu/factur-x 1.1.0 → 1.2.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/CHANGELOG.md CHANGED
@@ -7,6 +7,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.1] — 2026-08-27
11
+
12
+ - Expanded npm `keywords` (e.g. `e-rechnung`, `pdfa`, `chorus-pro`, `un-cefact`,
13
+ spelling variants) so the package is easier to find on npm. No code changes.
14
+
15
+ ## [1.2.0] — 2026-07-11
16
+
17
+ - **Updated to Factur-X 1.09 / ZUGFeRD 2.5** (spec dated 2026-06-10). Factur-X
18
+ 1.09 keeps the same UN/CEFACT CII **D22B** syntax, namespaces, and profile URNs
19
+ (`urn:factur-x.eu:1p0:*`) as 1.08, so this is a backward-compatible refresh:
20
+ XML produced by previous versions remains valid, and no input/output changes
21
+ are required.
22
+ - Bundled XSD schemas under `schema/` swapped to the official 1.09 set
23
+ (filenames normalized to the repo convention, internal `schemaLocation`
24
+ references rewritten to match). For MINIMUM / BASIC WL / BASIC / EN 16931 the
25
+ XSDs are content-identical to 1.08; the EXTENDED XSD gains only **optional**
26
+ additions (debited-account name, financial adjustment / charges on behalf of
27
+ a third party, an optional `listID` attribute on the allowance/charge reason
28
+ code).
29
+ - Reference `.sch` (Schematron) and `_codedb.xml` files updated to the 1.09
30
+ code lists and CEN validation rules (effective 2026-05-15). These are not
31
+ shipped in the npm package and not used at runtime — this library performs
32
+ XSD validation only.
33
+ - Documentation and code comments updated from "1.08 / 2.4" to "1.09 / 2.5".
34
+
35
+ - **New optional EXTENDED-profile input fields** for selected Factur-X 1.09
36
+ business terms (all additive, only emitted at `Profile.EXTENDED`):
37
+ - `PaymentInput.debtorAccountName` (BT-216) and `PaymentInput.debtorBic`
38
+ (BT-215) — debited-account name and its payment service provider BIC.
39
+ - `AllowanceChargeInput.exemptionReason` / `exemptionReasonCode`
40
+ (BT-173–176) — VAT exemption reason/code on document-level allowances and
41
+ charges.
42
+ - `FacturXInvoiceInput.financialAdjustments` (BG-34, new
43
+ `FinancialAdjustmentInput` with `reason` BT-180 + `amount` BT-179) —
44
+ charges collected on behalf of a third party.
45
+ - `InvoiceLineInput.manufacturer` (BG-X-94) — line-level product manufacturer
46
+ party (`ram:ManufacturerTradeParty`).
47
+ - Remaining 1.09 EXTENDED terms (e.g. document-level non-VAT tax codes,
48
+ logistic-service-charge exemption reasons) are still not emitted and can be
49
+ added later without breaking changes.
50
+
51
+ - **Fixed:** `ram:FormattedIssueDateTime` now emits a `qdt:DateTimeString` child
52
+ instead of `udt:DateTimeString`. It is typed as `qdt:FormattedDateTimeType` in
53
+ the CII XSD, so the previous `udt:` prefix failed XSD/Schematron validation for
54
+ every credit note or cancellation invoice referencing a dated preceding
55
+ invoice ([#5](https://github.com/StackForge-EU/factur-x/issues/5)).
56
+ - **Fixed:** XSD validation no longer exhausts libxml2's fixed-size input-callback
57
+ table. `validateXsd` now clears the table on each call, so validating many
58
+ documents in one process no longer causes spurious failures once ~15
59
+ validations have run.
60
+
10
61
  ## [1.1.0] — 2026-05-27
11
62
 
12
63
  - **BREAKING:** Every `ram:GlobalID` and the legal-organization `ram:ID` now
@@ -24,12 +75,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
24
75
  `ram:GlobalID` had the same defect as the party one)
25
76
  - `LegalOrganizationInput.schemeID?: string` added (optional, mirrors the
26
77
  conditional spec rule)
27
- Migration: `globalId: "4000001000005"` →
28
- `globalId: { value: "4000001000005", schemeID: "0088" }` (and the analogous
29
- rewrite for `standardIdentifier`). The new `IdentifierWithSchemeInput` type
30
- is exported from `src/index.ts`. Regression test added in
31
- `tests/xsd-validator.test.ts` that drives all three schemed identifiers
32
- through the EN16931 XSD in one go (thanks @sco-indy, #4).
78
+ Migration: `globalId: "4000001000005"` →
79
+ `globalId: { value: "4000001000005", schemeID: "0088" }` (and the analogous
80
+ rewrite for `standardIdentifier`). The new `IdentifierWithSchemeInput` type
81
+ is exported from `src/index.ts`. Regression test added in
82
+ `tests/xsd-validator.test.ts` that drives all three schemed identifiers
83
+ through the EN16931 XSD in one go (thanks @sco-indy, #4).
33
84
 
34
85
  ## [1.0.8] — 2026-05-27
35
86
 
@@ -76,7 +127,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
76
127
  debtor account last. Any invoice combining a SEPA direct debit
77
128
  (`payment.meansCode = "59"`) with `payment.debtorIban` plus a payee
78
129
  IBAN/BIC failed XSD validation with `Element 'PayerPartyDebtorFinancialAccount':
79
- This element is not expected`. Reordered the three blocks in
130
+ This element is not expected`. Reordered the three blocks in
80
131
  `src/core/xml-builder.ts`; regression test added in
81
132
  `tests/xml-builder.test.ts`.
82
133
 
@@ -153,6 +204,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
153
204
  - Deno compatibility test suite
154
205
 
155
206
  [Unreleased]: https://github.com/StackForge-EU/factur-x/commits/main
207
+ [1.2.1]: https://github.com/StackForge-EU/factur-x/compare/v1.2.0...v1.2.1
208
+ [1.2.0]: https://github.com/StackForge-EU/factur-x/compare/v1.1.0...v1.2.0
156
209
  [1.1.0]: https://github.com/StackForge-EU/factur-x/compare/v1.0.8...v1.1.0
157
210
  [1.0.8]: https://github.com/StackForge-EU/factur-x/compare/v1.0.7...v1.0.8
158
211
  [1.0.7]: https://github.com/StackForge-EU/factur-x/compare/v1.0.6...v1.0.7
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  This TypeScript/Node.js package takes a simple, typed invoice input object and:
14
14
 
15
15
  1. Validates it against profile requirements
16
- 2. Generates UN/CEFACT CII XML (Factur-X 1.08 / ZUGFeRD 2.4)
16
+ 2. Generates UN/CEFACT CII XML (Factur-X 1.09 / ZUGFeRD 2.5)
17
17
  3. Validates the XML against official XSD schemas (via WASM)
18
18
  4. Embeds it into a PDF with PDF/A-3b metadata
19
19
  5. Or outputs standalone XRechnung XML for German B2G use
@@ -68,8 +68,8 @@ import { embedFacturX, Profile } from "jsr:@stackforge-eu/factur-x";
68
68
 
69
69
  | Flavor | Region | Output | Notes |
70
70
  | ------------------- | ----------- | -------- | ----------------------------- |
71
- | `Flavor.FACTUR_X` | France / EU | PDF/A-3 | Default, Factur-X 1.08 |
72
- | `Flavor.ZUGFERD` | Germany | PDF/A-3 | ZUGFeRD 2.4 (= Factur-X 1.08) |
71
+ | `Flavor.FACTUR_X` | France / EU | PDF/A-3 | Default, Factur-X 1.09 |
72
+ | `Flavor.ZUGFERD` | Germany | PDF/A-3 | ZUGFeRD 2.5 (= Factur-X 1.09) |
73
73
  | `Flavor.XRECHNUNG` | Germany B2G | XML only | PEPPOL business process |
74
74
  | `Flavor.CHRONO_PRO` | Belgium | PDF/A-3 | Chrono Pro conventions |
75
75
 
package/dist/index.cjs CHANGED
@@ -235,7 +235,7 @@ var FLAVOR_CONFIGS = {
235
235
  defaultTypeCode: "380" /* COMMERCIAL_INVOICE */,
236
236
  attachmentFilename: "factur-x.xml",
237
237
  embedInPdf: true,
238
- description: "German electronic invoice format. ZUGFeRD 2.4 uses factur-x.xml."
238
+ description: "German electronic invoice format. ZUGFeRD 2.5 uses factur-x.xml."
239
239
  },
240
240
  ["xrechnung" /* XRECHNUNG */]: {
241
241
  name: "XRechnung",
@@ -312,7 +312,8 @@ function tag(name, content, attrs) {
312
312
  return `<${name}${a}>${content}</${name}>`;
313
313
  }
314
314
  function dateEl(wrapper, isoDate) {
315
- return tag(wrapper, tag("udt:DateTimeString", formatDate(isoDate), { format: "102" }));
315
+ const child = wrapper === "ram:FormattedIssueDateTime" ? "qdt:DateTimeString" : "udt:DateTimeString";
316
+ return tag(wrapper, tag(child, formatDate(isoDate), { format: "102" }));
316
317
  }
317
318
  function buildAddress(addr) {
318
319
  let x = "";
@@ -393,6 +394,8 @@ function buildLineItem(line, profile) {
393
394
  if (line.description) prod += tag("ram:Description", escapeXml(line.description));
394
395
  if (line.originCountry && atLeast(profile, "EN16931" /* EN16931 */))
395
396
  prod += tag("ram:OriginTradeCountry", tag("ram:ID", escapeXml(line.originCountry)));
397
+ if (line.manufacturer && atLeast(profile, "EXTENDED" /* EXTENDED */))
398
+ prod += tag("ram:ManufacturerTradeParty", buildParty(line.manufacturer, profile));
396
399
  let agree = "";
397
400
  if (line.buyerOrderLineId && atLeast(profile, "EN16931" /* EN16931 */))
398
401
  agree += tag(
@@ -427,7 +430,7 @@ function buildLineItem(line, profile) {
427
430
  tag("ram:AssociatedDocumentLineDocument", doc) + tag("ram:SpecifiedTradeProduct", prod) + tag("ram:SpecifiedLineTradeAgreement", agree) + tag("ram:SpecifiedLineTradeDelivery", delivery) + tag("ram:SpecifiedLineTradeSettlement", settle)
428
431
  );
429
432
  }
430
- function buildAllowanceCharge(ac) {
433
+ function buildAllowanceCharge(ac, profile) {
431
434
  let x = tag("ram:ChargeIndicator", tag("udt:Indicator", ac.isCharge ? "true" : "false"));
432
435
  if (ac.percent !== void 0) x += tag("ram:CalculationPercent", ac.percent.toString());
433
436
  if (ac.baseAmount !== void 0) x += tag("ram:BasisAmount", fmtAmt(ac.baseAmount));
@@ -435,8 +438,13 @@ function buildAllowanceCharge(ac) {
435
438
  if (ac.reasonCode) x += tag("ram:ReasonCode", escapeXml(ac.reasonCode));
436
439
  if (ac.reason) x += tag("ram:Reason", escapeXml(ac.reason));
437
440
  if (ac.vatCategoryCode || ac.vatRatePercent !== void 0) {
441
+ const extended = atLeast(profile, "EXTENDED" /* EXTENDED */);
438
442
  let tx = tag("ram:TypeCode", "VAT");
443
+ if (extended && ac.exemptionReason)
444
+ tx += tag("ram:ExemptionReason", escapeXml(ac.exemptionReason));
439
445
  if (ac.vatCategoryCode) tx += tag("ram:CategoryCode", escapeXml(ac.vatCategoryCode));
446
+ if (extended && ac.exemptionReasonCode)
447
+ tx += tag("ram:ExemptionReasonCode", escapeXml(ac.exemptionReasonCode));
440
448
  if (ac.vatRatePercent !== void 0)
441
449
  tx += tag("ram:RateApplicablePercent", ac.vatRatePercent.toString());
442
450
  x += tag("ram:CategoryTradeTax", tx);
@@ -604,11 +612,12 @@ function buildXml(input, profile, flavor) {
604
612
  sett += tag("ram:PayeeTradeParty", buildParty(input.payee, profile));
605
613
  if (payment?.meansCode && atLeast(profile, "BASIC_WL" /* BASIC_WL */)) {
606
614
  let pm = tag("ram:TypeCode", escapeXml(payment.meansCode));
607
- if (payment.debtorIban)
608
- pm += tag(
609
- "ram:PayerPartyDebtorFinancialAccount",
610
- tag("ram:IBANID", escapeXml(payment.debtorIban))
611
- );
615
+ if (payment.debtorIban) {
616
+ let dacct = tag("ram:IBANID", escapeXml(payment.debtorIban));
617
+ if (payment.debtorAccountName && atLeast(profile, "EXTENDED" /* EXTENDED */))
618
+ dacct += tag("ram:AccountName", escapeXml(payment.debtorAccountName));
619
+ pm += tag("ram:PayerPartyDebtorFinancialAccount", dacct);
620
+ }
612
621
  if (payment.iban || payment.accountId || payment.accountName) {
613
622
  let acct = "";
614
623
  if (payment.iban) acct += tag("ram:IBANID", escapeXml(payment.iban));
@@ -617,6 +626,11 @@ function buildXml(input, profile, flavor) {
617
626
  acct += tag("ram:AccountName", escapeXml(payment.accountName));
618
627
  pm += tag("ram:PayeePartyCreditorFinancialAccount", acct);
619
628
  }
629
+ if (payment.debtorBic && atLeast(profile, "EXTENDED" /* EXTENDED */))
630
+ pm += tag(
631
+ "ram:PayerSpecifiedDebtorFinancialInstitution",
632
+ tag("ram:BICID", escapeXml(payment.debtorBic))
633
+ );
620
634
  if (payment.bic && atLeast(profile, "EN16931" /* EN16931 */))
621
635
  pm += tag(
622
636
  "ram:PayeeSpecifiedCreditorFinancialInstitution",
@@ -634,7 +648,7 @@ function buildXml(input, profile, flavor) {
634
648
  sett += tag("ram:BillingSpecifiedPeriod", bp);
635
649
  }
636
650
  if (input.allowancesCharges && atLeast(profile, "BASIC_WL" /* BASIC_WL */))
637
- for (const ac of input.allowancesCharges) sett += buildAllowanceCharge(ac);
651
+ for (const ac of input.allowancesCharges) sett += buildAllowanceCharge(ac, profile);
638
652
  const dueDate = payment?.dueDate ?? doc.dueDate;
639
653
  if (atLeast(profile, "BASIC_WL" /* BASIC_WL */) && (payment?.termsDescription || dueDate || payment?.mandateId)) {
640
654
  let pt = "";
@@ -645,6 +659,14 @@ function buildXml(input, profile, flavor) {
645
659
  sett += tag("ram:SpecifiedTradePaymentTerms", pt);
646
660
  }
647
661
  sett += buildMonetarySummation(totals, profile);
662
+ if (input.financialAdjustments && atLeast(profile, "EXTENDED" /* EXTENDED */)) {
663
+ for (const fa of input.financialAdjustments) {
664
+ sett += tag(
665
+ "ram:SpecifiedFinancialAdjustment",
666
+ tag("ram:Reason", escapeXml(fa.reason)) + tag("ram:ActualAmount", fmtAmt(fa.amount))
667
+ );
668
+ }
669
+ }
648
670
  if (input.references && atLeast(profile, "BASIC_WL" /* BASIC_WL */)) {
649
671
  for (const ref of input.references) {
650
672
  if (ref.type === "preceding") {
@@ -1077,25 +1099,43 @@ async function validateXsd(xml, profile, options) {
1077
1099
  XsdValidator,
1078
1100
  XmlValidateError,
1079
1101
  xmlRegisterInputProvider,
1080
- XmlBufferInputProvider
1102
+ xmlCleanupInputProvider,
1103
+ openBuffer,
1104
+ readBuffer,
1105
+ closeBuffer
1081
1106
  } = await import('libxml2-wasm');
1082
1107
  const schemaDir = path__namespace.dirname(xsdPath);
1083
1108
  const files = fs__namespace.readdirSync(schemaDir).filter((f) => f.endsWith(".xsd"));
1084
1109
  const buffers = {};
1085
1110
  for (const file of files) {
1086
- const filePath = path__namespace.join(schemaDir, file);
1087
- buffers[filePath] = fs__namespace.readFileSync(filePath);
1088
- buffers[`file://${filePath}`] = buffers[filePath];
1089
- buffers[file] = buffers[filePath];
1090
- }
1091
- const provider = new XmlBufferInputProvider(buffers);
1092
- xmlRegisterInputProvider(provider);
1111
+ buffers[file] = fs__namespace.readFileSync(path__namespace.join(schemaDir, file));
1112
+ }
1113
+ const schemaFileFor = (requested) => {
1114
+ const start = Math.max(requested.lastIndexOf("/"), requested.lastIndexOf("\\")) + 1;
1115
+ const segment = requested.slice(start);
1116
+ let name = segment;
1117
+ try {
1118
+ name = decodeURIComponent(segment);
1119
+ } catch {
1120
+ }
1121
+ return files.includes(name) ? name : void 0;
1122
+ };
1123
+ xmlCleanupInputProvider();
1124
+ xmlRegisterInputProvider({
1125
+ match: (filename) => schemaFileFor(filename) !== void 0,
1126
+ open: (filename) => openBuffer(buffers[schemaFileFor(filename)]),
1127
+ read: readBuffer,
1128
+ close: (fd) => {
1129
+ closeBuffer(fd);
1130
+ return true;
1131
+ }
1132
+ });
1093
1133
  let xsdDoc;
1094
1134
  let validator;
1095
1135
  let xmlDoc;
1096
1136
  try {
1097
1137
  const xsdContent = fs__namespace.readFileSync(xsdPath, "utf-8");
1098
- xsdDoc = XmlDocument.fromString(xsdContent, { url: `file://${xsdPath}` });
1138
+ xsdDoc = XmlDocument.fromString(xsdContent, { url: url.pathToFileURL(xsdPath).href });
1099
1139
  validator = XsdValidator.fromDoc(xsdDoc);
1100
1140
  xmlDoc = XmlDocument.fromString(xml);
1101
1141
  validator.validate(xmlDoc);
@@ -1117,6 +1157,7 @@ async function validateXsd(xml, profile, options) {
1117
1157
  xmlDoc?.dispose();
1118
1158
  validator?.dispose();
1119
1159
  xsdDoc?.dispose();
1160
+ xmlCleanupInputProvider();
1120
1161
  }
1121
1162
  }
1122
1163
  var AF_RELATIONSHIP_MAP = {
@@ -1366,7 +1407,7 @@ async function embedFacturX(options) {
1366
1407
  const xmlBytes = new TextEncoder().encode(xml);
1367
1408
  const afRel = resolveAfRelationship(profile, options.afRelationship);
1368
1409
  await pdfDoc.attach(xmlBytes, flavorConfig.attachmentFilename, {
1369
- mimeType: "text/xml",
1410
+ mimeType: "application/xml",
1370
1411
  afRelationship: afRel,
1371
1412
  description: "Factur-X Invoice"
1372
1413
  });
package/dist/index.d.cts CHANGED
@@ -633,6 +633,14 @@ interface InvoiceLineInput {
633
633
  * @since EN16931
634
634
  */
635
635
  buyerOrderLineId?: string;
636
+ /**
637
+ * Product manufacturer of this line item. Uses the standard trade-party
638
+ * shape; only id/globalId (BT-X-600), name (BT-X-598), and postal address
639
+ * (BG-X-93) are typically relevant.
640
+ * @see Factur-X EXTENDED BG-X-94, Factur-X 1.09
641
+ * @since EXTENDED
642
+ */
643
+ manufacturer?: TradePartyInput;
636
644
  }
637
645
  /**
638
646
  * Allowance or charge at header or line level.
@@ -666,6 +674,18 @@ interface AllowanceChargeInput {
666
674
  vatCategoryCode?: VatCategoryCode | (string & Record<never, never>);
667
675
  /** VAT rate for this allowance/charge */
668
676
  vatRatePercent?: number;
677
+ /**
678
+ * VAT exemption reason text for this document-level allowance/charge.
679
+ * @see Factur-X EXTENDED BT-173 (allowance) / BT-175 (charge), Factur-X 1.09
680
+ * @since EXTENDED
681
+ */
682
+ exemptionReason?: string;
683
+ /**
684
+ * VAT exemption reason code for this document-level allowance/charge.
685
+ * @see Factur-X EXTENDED BT-174 (allowance) / BT-176 (charge), Factur-X 1.09
686
+ * @since EXTENDED
687
+ */
688
+ exemptionReasonCode?: string;
669
689
  }
670
690
  /**
671
691
  * Payment information.
@@ -726,6 +746,22 @@ interface PaymentInput {
726
746
  * @see EN 16931 BT-91
727
747
  */
728
748
  debtorIban?: string;
749
+ /**
750
+ * Debtor account name (holder of the debited account). Only emitted when
751
+ * {@link PaymentInput.debtorIban} is also set, since the CII schema requires
752
+ * the IBAN on the debtor account element.
753
+ * @see Factur-X EXTENDED BT-216 ("Debited account name", Factur-X 1.09)
754
+ * @since EXTENDED
755
+ */
756
+ debtorAccountName?: string;
757
+ /**
758
+ * BIC/SWIFT of the debtor's payment service provider (the debited account's
759
+ * financial institution).
760
+ * @see Factur-X EXTENDED BT-215 ("Debited account payment service provider
761
+ * identifier", Factur-X 1.09)
762
+ * @since EXTENDED
763
+ */
764
+ debtorBic?: string;
729
765
  /**
730
766
  * Payment terms description (free text).
731
767
  * @see EN 16931 BT-20
@@ -974,6 +1010,30 @@ interface FacturXInvoiceInput {
974
1010
  * @since BASIC_WL
975
1011
  */
976
1012
  sellerTaxRepresentative?: TradePartyInput;
1013
+ /**
1014
+ * Charges collected on behalf of a third party (document level).
1015
+ * @see Factur-X EXTENDED BG-34, Factur-X 1.09
1016
+ * @since EXTENDED
1017
+ */
1018
+ financialAdjustments?: FinancialAdjustmentInput[];
1019
+ }
1020
+ /**
1021
+ * A charge collected on behalf of a third party.
1022
+ *
1023
+ * @see Factur-X EXTENDED BG-34 (`ram:SpecifiedFinancialAdjustment`), Factur-X 1.09
1024
+ * @since EXTENDED
1025
+ */
1026
+ interface FinancialAdjustmentInput {
1027
+ /**
1028
+ * Specification of the charge collected on behalf of a third party.
1029
+ * @see Factur-X EXTENDED BT-180
1030
+ */
1031
+ reason: string;
1032
+ /**
1033
+ * Charge amount collected on behalf of a third party.
1034
+ * @see Factur-X EXTENDED BT-179
1035
+ */
1036
+ amount: number;
977
1037
  }
978
1038
 
979
1039
  /**
@@ -1094,7 +1154,7 @@ declare function escapeXml(value: string): string;
1094
1154
  /**
1095
1155
  * Builds a UN/CEFACT CrossIndustryInvoice XML string from structured input.
1096
1156
  *
1097
- * The output conforms to the Factur-X 1.08 / ZUGFeRD 2.4 CII schema at the
1157
+ * The output conforms to the Factur-X 1.09 / ZUGFeRD 2.5 CII schema at the
1098
1158
  * requested {@link Profile} level. Elements that do not belong to the chosen
1099
1159
  * profile are silently omitted.
1100
1160
  *
@@ -1452,4 +1512,4 @@ interface XRechnungResult {
1452
1512
  */
1453
1513
  declare function toXRechnung(input: FacturXInvoiceInput, options?: XRechnungOptions): XRechnungResult;
1454
1514
 
1455
- export { type AddressInput, type AllowanceChargeInput, type BillingPeriodInput, type ContactInput, type DeliveryInput, type DocumentReferenceInput, DocumentTypeCode, type EmbedOptions, type EmbedResult, type ExtractOptions, type ExtractResult, FLAVOR_CONFIGS, FLAVOR_DEFAULT_TYPE_CODES, type FacturXInvoiceInput, Flavor, type FlavorConfig, type IdentifierWithSchemeInput, type InvoiceDocumentInput, type InvoiceLineInput, type InvoiceTotalsInput, type LegalOrganizationInput, type NoteInput, PROFILE_MAIN_XSD, PROFILE_SCHEMA_DIRS, PROFILE_URNS, type PaymentInput, Profile, type TaxRegistrationInput, type TradePartyInput, UnitCode, type ValidationError, type ValidationResult, type VatBreakdownInput, VatCategoryCode, XRECHNUNG_PROFILE_URN, type XRechnungOptions, type XRechnungResult, type XsdValidateOptions, type XsdValidationError, type XsdValidationResult, buildXml, embedFacturX, escapeXml, extractXml, getFlavorConfig, resolveBusinessProcessUrn, resolveTypeCode, toXRechnung, validateFlavorProfile, validateInput, validateXsd };
1515
+ export { type AddressInput, type AllowanceChargeInput, type BillingPeriodInput, type ContactInput, type DeliveryInput, type DocumentReferenceInput, DocumentTypeCode, type EmbedOptions, type EmbedResult, type ExtractOptions, type ExtractResult, FLAVOR_CONFIGS, FLAVOR_DEFAULT_TYPE_CODES, type FacturXInvoiceInput, type FinancialAdjustmentInput, Flavor, type FlavorConfig, type IdentifierWithSchemeInput, type InvoiceDocumentInput, type InvoiceLineInput, type InvoiceTotalsInput, type LegalOrganizationInput, type NoteInput, PROFILE_MAIN_XSD, PROFILE_SCHEMA_DIRS, PROFILE_URNS, type PaymentInput, Profile, type TaxRegistrationInput, type TradePartyInput, UnitCode, type ValidationError, type ValidationResult, type VatBreakdownInput, VatCategoryCode, XRECHNUNG_PROFILE_URN, type XRechnungOptions, type XRechnungResult, type XsdValidateOptions, type XsdValidationError, type XsdValidationResult, buildXml, embedFacturX, escapeXml, extractXml, getFlavorConfig, resolveBusinessProcessUrn, resolveTypeCode, toXRechnung, validateFlavorProfile, validateInput, validateXsd };
package/dist/index.d.ts CHANGED
@@ -633,6 +633,14 @@ interface InvoiceLineInput {
633
633
  * @since EN16931
634
634
  */
635
635
  buyerOrderLineId?: string;
636
+ /**
637
+ * Product manufacturer of this line item. Uses the standard trade-party
638
+ * shape; only id/globalId (BT-X-600), name (BT-X-598), and postal address
639
+ * (BG-X-93) are typically relevant.
640
+ * @see Factur-X EXTENDED BG-X-94, Factur-X 1.09
641
+ * @since EXTENDED
642
+ */
643
+ manufacturer?: TradePartyInput;
636
644
  }
637
645
  /**
638
646
  * Allowance or charge at header or line level.
@@ -666,6 +674,18 @@ interface AllowanceChargeInput {
666
674
  vatCategoryCode?: VatCategoryCode | (string & Record<never, never>);
667
675
  /** VAT rate for this allowance/charge */
668
676
  vatRatePercent?: number;
677
+ /**
678
+ * VAT exemption reason text for this document-level allowance/charge.
679
+ * @see Factur-X EXTENDED BT-173 (allowance) / BT-175 (charge), Factur-X 1.09
680
+ * @since EXTENDED
681
+ */
682
+ exemptionReason?: string;
683
+ /**
684
+ * VAT exemption reason code for this document-level allowance/charge.
685
+ * @see Factur-X EXTENDED BT-174 (allowance) / BT-176 (charge), Factur-X 1.09
686
+ * @since EXTENDED
687
+ */
688
+ exemptionReasonCode?: string;
669
689
  }
670
690
  /**
671
691
  * Payment information.
@@ -726,6 +746,22 @@ interface PaymentInput {
726
746
  * @see EN 16931 BT-91
727
747
  */
728
748
  debtorIban?: string;
749
+ /**
750
+ * Debtor account name (holder of the debited account). Only emitted when
751
+ * {@link PaymentInput.debtorIban} is also set, since the CII schema requires
752
+ * the IBAN on the debtor account element.
753
+ * @see Factur-X EXTENDED BT-216 ("Debited account name", Factur-X 1.09)
754
+ * @since EXTENDED
755
+ */
756
+ debtorAccountName?: string;
757
+ /**
758
+ * BIC/SWIFT of the debtor's payment service provider (the debited account's
759
+ * financial institution).
760
+ * @see Factur-X EXTENDED BT-215 ("Debited account payment service provider
761
+ * identifier", Factur-X 1.09)
762
+ * @since EXTENDED
763
+ */
764
+ debtorBic?: string;
729
765
  /**
730
766
  * Payment terms description (free text).
731
767
  * @see EN 16931 BT-20
@@ -974,6 +1010,30 @@ interface FacturXInvoiceInput {
974
1010
  * @since BASIC_WL
975
1011
  */
976
1012
  sellerTaxRepresentative?: TradePartyInput;
1013
+ /**
1014
+ * Charges collected on behalf of a third party (document level).
1015
+ * @see Factur-X EXTENDED BG-34, Factur-X 1.09
1016
+ * @since EXTENDED
1017
+ */
1018
+ financialAdjustments?: FinancialAdjustmentInput[];
1019
+ }
1020
+ /**
1021
+ * A charge collected on behalf of a third party.
1022
+ *
1023
+ * @see Factur-X EXTENDED BG-34 (`ram:SpecifiedFinancialAdjustment`), Factur-X 1.09
1024
+ * @since EXTENDED
1025
+ */
1026
+ interface FinancialAdjustmentInput {
1027
+ /**
1028
+ * Specification of the charge collected on behalf of a third party.
1029
+ * @see Factur-X EXTENDED BT-180
1030
+ */
1031
+ reason: string;
1032
+ /**
1033
+ * Charge amount collected on behalf of a third party.
1034
+ * @see Factur-X EXTENDED BT-179
1035
+ */
1036
+ amount: number;
977
1037
  }
978
1038
 
979
1039
  /**
@@ -1094,7 +1154,7 @@ declare function escapeXml(value: string): string;
1094
1154
  /**
1095
1155
  * Builds a UN/CEFACT CrossIndustryInvoice XML string from structured input.
1096
1156
  *
1097
- * The output conforms to the Factur-X 1.08 / ZUGFeRD 2.4 CII schema at the
1157
+ * The output conforms to the Factur-X 1.09 / ZUGFeRD 2.5 CII schema at the
1098
1158
  * requested {@link Profile} level. Elements that do not belong to the chosen
1099
1159
  * profile are silently omitted.
1100
1160
  *
@@ -1452,4 +1512,4 @@ interface XRechnungResult {
1452
1512
  */
1453
1513
  declare function toXRechnung(input: FacturXInvoiceInput, options?: XRechnungOptions): XRechnungResult;
1454
1514
 
1455
- export { type AddressInput, type AllowanceChargeInput, type BillingPeriodInput, type ContactInput, type DeliveryInput, type DocumentReferenceInput, DocumentTypeCode, type EmbedOptions, type EmbedResult, type ExtractOptions, type ExtractResult, FLAVOR_CONFIGS, FLAVOR_DEFAULT_TYPE_CODES, type FacturXInvoiceInput, Flavor, type FlavorConfig, type IdentifierWithSchemeInput, type InvoiceDocumentInput, type InvoiceLineInput, type InvoiceTotalsInput, type LegalOrganizationInput, type NoteInput, PROFILE_MAIN_XSD, PROFILE_SCHEMA_DIRS, PROFILE_URNS, type PaymentInput, Profile, type TaxRegistrationInput, type TradePartyInput, UnitCode, type ValidationError, type ValidationResult, type VatBreakdownInput, VatCategoryCode, XRECHNUNG_PROFILE_URN, type XRechnungOptions, type XRechnungResult, type XsdValidateOptions, type XsdValidationError, type XsdValidationResult, buildXml, embedFacturX, escapeXml, extractXml, getFlavorConfig, resolveBusinessProcessUrn, resolveTypeCode, toXRechnung, validateFlavorProfile, validateInput, validateXsd };
1515
+ export { type AddressInput, type AllowanceChargeInput, type BillingPeriodInput, type ContactInput, type DeliveryInput, type DocumentReferenceInput, DocumentTypeCode, type EmbedOptions, type EmbedResult, type ExtractOptions, type ExtractResult, FLAVOR_CONFIGS, FLAVOR_DEFAULT_TYPE_CODES, type FacturXInvoiceInput, type FinancialAdjustmentInput, Flavor, type FlavorConfig, type IdentifierWithSchemeInput, type InvoiceDocumentInput, type InvoiceLineInput, type InvoiceTotalsInput, type LegalOrganizationInput, type NoteInput, PROFILE_MAIN_XSD, PROFILE_SCHEMA_DIRS, PROFILE_URNS, type PaymentInput, Profile, type TaxRegistrationInput, type TradePartyInput, UnitCode, type ValidationError, type ValidationResult, type VatBreakdownInput, VatCategoryCode, XRECHNUNG_PROFILE_URN, type XRechnungOptions, type XRechnungResult, type XsdValidateOptions, type XsdValidationError, type XsdValidationResult, buildXml, embedFacturX, escapeXml, extractXml, getFlavorConfig, resolveBusinessProcessUrn, resolveTypeCode, toXRechnung, validateFlavorProfile, validateInput, validateXsd };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
- import { fileURLToPath } from 'url';
3
+ import { pathToFileURL, fileURLToPath } from 'url';
4
4
  import console from 'console';
5
5
  import { createHash } from 'crypto';
6
6
  import { AFRelationship, PDFDocument, PDFName, PDFArray, PDFDict, PDFStream, PDFRawStream, decodePDFRawStream, PDFString, PDFHexString, PDFRef } from 'pdf-lib';
@@ -205,7 +205,7 @@ var FLAVOR_CONFIGS = {
205
205
  defaultTypeCode: "380" /* COMMERCIAL_INVOICE */,
206
206
  attachmentFilename: "factur-x.xml",
207
207
  embedInPdf: true,
208
- description: "German electronic invoice format. ZUGFeRD 2.4 uses factur-x.xml."
208
+ description: "German electronic invoice format. ZUGFeRD 2.5 uses factur-x.xml."
209
209
  },
210
210
  ["xrechnung" /* XRECHNUNG */]: {
211
211
  name: "XRechnung",
@@ -282,7 +282,8 @@ function tag(name, content, attrs) {
282
282
  return `<${name}${a}>${content}</${name}>`;
283
283
  }
284
284
  function dateEl(wrapper, isoDate) {
285
- return tag(wrapper, tag("udt:DateTimeString", formatDate(isoDate), { format: "102" }));
285
+ const child = wrapper === "ram:FormattedIssueDateTime" ? "qdt:DateTimeString" : "udt:DateTimeString";
286
+ return tag(wrapper, tag(child, formatDate(isoDate), { format: "102" }));
286
287
  }
287
288
  function buildAddress(addr) {
288
289
  let x = "";
@@ -363,6 +364,8 @@ function buildLineItem(line, profile) {
363
364
  if (line.description) prod += tag("ram:Description", escapeXml(line.description));
364
365
  if (line.originCountry && atLeast(profile, "EN16931" /* EN16931 */))
365
366
  prod += tag("ram:OriginTradeCountry", tag("ram:ID", escapeXml(line.originCountry)));
367
+ if (line.manufacturer && atLeast(profile, "EXTENDED" /* EXTENDED */))
368
+ prod += tag("ram:ManufacturerTradeParty", buildParty(line.manufacturer, profile));
366
369
  let agree = "";
367
370
  if (line.buyerOrderLineId && atLeast(profile, "EN16931" /* EN16931 */))
368
371
  agree += tag(
@@ -397,7 +400,7 @@ function buildLineItem(line, profile) {
397
400
  tag("ram:AssociatedDocumentLineDocument", doc) + tag("ram:SpecifiedTradeProduct", prod) + tag("ram:SpecifiedLineTradeAgreement", agree) + tag("ram:SpecifiedLineTradeDelivery", delivery) + tag("ram:SpecifiedLineTradeSettlement", settle)
398
401
  );
399
402
  }
400
- function buildAllowanceCharge(ac) {
403
+ function buildAllowanceCharge(ac, profile) {
401
404
  let x = tag("ram:ChargeIndicator", tag("udt:Indicator", ac.isCharge ? "true" : "false"));
402
405
  if (ac.percent !== void 0) x += tag("ram:CalculationPercent", ac.percent.toString());
403
406
  if (ac.baseAmount !== void 0) x += tag("ram:BasisAmount", fmtAmt(ac.baseAmount));
@@ -405,8 +408,13 @@ function buildAllowanceCharge(ac) {
405
408
  if (ac.reasonCode) x += tag("ram:ReasonCode", escapeXml(ac.reasonCode));
406
409
  if (ac.reason) x += tag("ram:Reason", escapeXml(ac.reason));
407
410
  if (ac.vatCategoryCode || ac.vatRatePercent !== void 0) {
411
+ const extended = atLeast(profile, "EXTENDED" /* EXTENDED */);
408
412
  let tx = tag("ram:TypeCode", "VAT");
413
+ if (extended && ac.exemptionReason)
414
+ tx += tag("ram:ExemptionReason", escapeXml(ac.exemptionReason));
409
415
  if (ac.vatCategoryCode) tx += tag("ram:CategoryCode", escapeXml(ac.vatCategoryCode));
416
+ if (extended && ac.exemptionReasonCode)
417
+ tx += tag("ram:ExemptionReasonCode", escapeXml(ac.exemptionReasonCode));
410
418
  if (ac.vatRatePercent !== void 0)
411
419
  tx += tag("ram:RateApplicablePercent", ac.vatRatePercent.toString());
412
420
  x += tag("ram:CategoryTradeTax", tx);
@@ -574,11 +582,12 @@ function buildXml(input, profile, flavor) {
574
582
  sett += tag("ram:PayeeTradeParty", buildParty(input.payee, profile));
575
583
  if (payment?.meansCode && atLeast(profile, "BASIC_WL" /* BASIC_WL */)) {
576
584
  let pm = tag("ram:TypeCode", escapeXml(payment.meansCode));
577
- if (payment.debtorIban)
578
- pm += tag(
579
- "ram:PayerPartyDebtorFinancialAccount",
580
- tag("ram:IBANID", escapeXml(payment.debtorIban))
581
- );
585
+ if (payment.debtorIban) {
586
+ let dacct = tag("ram:IBANID", escapeXml(payment.debtorIban));
587
+ if (payment.debtorAccountName && atLeast(profile, "EXTENDED" /* EXTENDED */))
588
+ dacct += tag("ram:AccountName", escapeXml(payment.debtorAccountName));
589
+ pm += tag("ram:PayerPartyDebtorFinancialAccount", dacct);
590
+ }
582
591
  if (payment.iban || payment.accountId || payment.accountName) {
583
592
  let acct = "";
584
593
  if (payment.iban) acct += tag("ram:IBANID", escapeXml(payment.iban));
@@ -587,6 +596,11 @@ function buildXml(input, profile, flavor) {
587
596
  acct += tag("ram:AccountName", escapeXml(payment.accountName));
588
597
  pm += tag("ram:PayeePartyCreditorFinancialAccount", acct);
589
598
  }
599
+ if (payment.debtorBic && atLeast(profile, "EXTENDED" /* EXTENDED */))
600
+ pm += tag(
601
+ "ram:PayerSpecifiedDebtorFinancialInstitution",
602
+ tag("ram:BICID", escapeXml(payment.debtorBic))
603
+ );
590
604
  if (payment.bic && atLeast(profile, "EN16931" /* EN16931 */))
591
605
  pm += tag(
592
606
  "ram:PayeeSpecifiedCreditorFinancialInstitution",
@@ -604,7 +618,7 @@ function buildXml(input, profile, flavor) {
604
618
  sett += tag("ram:BillingSpecifiedPeriod", bp);
605
619
  }
606
620
  if (input.allowancesCharges && atLeast(profile, "BASIC_WL" /* BASIC_WL */))
607
- for (const ac of input.allowancesCharges) sett += buildAllowanceCharge(ac);
621
+ for (const ac of input.allowancesCharges) sett += buildAllowanceCharge(ac, profile);
608
622
  const dueDate = payment?.dueDate ?? doc.dueDate;
609
623
  if (atLeast(profile, "BASIC_WL" /* BASIC_WL */) && (payment?.termsDescription || dueDate || payment?.mandateId)) {
610
624
  let pt = "";
@@ -615,6 +629,14 @@ function buildXml(input, profile, flavor) {
615
629
  sett += tag("ram:SpecifiedTradePaymentTerms", pt);
616
630
  }
617
631
  sett += buildMonetarySummation(totals, profile);
632
+ if (input.financialAdjustments && atLeast(profile, "EXTENDED" /* EXTENDED */)) {
633
+ for (const fa of input.financialAdjustments) {
634
+ sett += tag(
635
+ "ram:SpecifiedFinancialAdjustment",
636
+ tag("ram:Reason", escapeXml(fa.reason)) + tag("ram:ActualAmount", fmtAmt(fa.amount))
637
+ );
638
+ }
639
+ }
618
640
  if (input.references && atLeast(profile, "BASIC_WL" /* BASIC_WL */)) {
619
641
  for (const ref of input.references) {
620
642
  if (ref.type === "preceding") {
@@ -1047,25 +1069,43 @@ async function validateXsd(xml, profile, options) {
1047
1069
  XsdValidator,
1048
1070
  XmlValidateError,
1049
1071
  xmlRegisterInputProvider,
1050
- XmlBufferInputProvider
1072
+ xmlCleanupInputProvider,
1073
+ openBuffer,
1074
+ readBuffer,
1075
+ closeBuffer
1051
1076
  } = await import('libxml2-wasm');
1052
1077
  const schemaDir = path.dirname(xsdPath);
1053
1078
  const files = fs.readdirSync(schemaDir).filter((f) => f.endsWith(".xsd"));
1054
1079
  const buffers = {};
1055
1080
  for (const file of files) {
1056
- const filePath = path.join(schemaDir, file);
1057
- buffers[filePath] = fs.readFileSync(filePath);
1058
- buffers[`file://${filePath}`] = buffers[filePath];
1059
- buffers[file] = buffers[filePath];
1060
- }
1061
- const provider = new XmlBufferInputProvider(buffers);
1062
- xmlRegisterInputProvider(provider);
1081
+ buffers[file] = fs.readFileSync(path.join(schemaDir, file));
1082
+ }
1083
+ const schemaFileFor = (requested) => {
1084
+ const start = Math.max(requested.lastIndexOf("/"), requested.lastIndexOf("\\")) + 1;
1085
+ const segment = requested.slice(start);
1086
+ let name = segment;
1087
+ try {
1088
+ name = decodeURIComponent(segment);
1089
+ } catch {
1090
+ }
1091
+ return files.includes(name) ? name : void 0;
1092
+ };
1093
+ xmlCleanupInputProvider();
1094
+ xmlRegisterInputProvider({
1095
+ match: (filename) => schemaFileFor(filename) !== void 0,
1096
+ open: (filename) => openBuffer(buffers[schemaFileFor(filename)]),
1097
+ read: readBuffer,
1098
+ close: (fd) => {
1099
+ closeBuffer(fd);
1100
+ return true;
1101
+ }
1102
+ });
1063
1103
  let xsdDoc;
1064
1104
  let validator;
1065
1105
  let xmlDoc;
1066
1106
  try {
1067
1107
  const xsdContent = fs.readFileSync(xsdPath, "utf-8");
1068
- xsdDoc = XmlDocument.fromString(xsdContent, { url: `file://${xsdPath}` });
1108
+ xsdDoc = XmlDocument.fromString(xsdContent, { url: pathToFileURL(xsdPath).href });
1069
1109
  validator = XsdValidator.fromDoc(xsdDoc);
1070
1110
  xmlDoc = XmlDocument.fromString(xml);
1071
1111
  validator.validate(xmlDoc);
@@ -1087,6 +1127,7 @@ async function validateXsd(xml, profile, options) {
1087
1127
  xmlDoc?.dispose();
1088
1128
  validator?.dispose();
1089
1129
  xsdDoc?.dispose();
1130
+ xmlCleanupInputProvider();
1090
1131
  }
1091
1132
  }
1092
1133
  var AF_RELATIONSHIP_MAP = {
@@ -1336,7 +1377,7 @@ async function embedFacturX(options) {
1336
1377
  const xmlBytes = new TextEncoder().encode(xml);
1337
1378
  const afRel = resolveAfRelationship(profile, options.afRelationship);
1338
1379
  await pdfDoc.attach(xmlBytes, flavorConfig.attachmentFilename, {
1339
- mimeType: "text/xml",
1380
+ mimeType: "application/xml",
1340
1381
  afRelationship: afRel,
1341
1382
  description: "Factur-X Invoice"
1342
1383
  });
package/package.json CHANGED
@@ -1,21 +1,39 @@
1
1
  {
2
2
  "name": "@stackforge-eu/factur-x",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "description": "Embed Factur-X, ZUGFeRD, and XRechnung structured invoice XML into PDF/A-3 documents",
6
6
  "keywords": [
7
7
  "factur-x",
8
+ "facturx",
8
9
  "zugferd",
9
10
  "xrechnung",
11
+ "e-rechnung",
12
+ "chorus-pro",
10
13
  "en16931",
14
+ "en-16931",
11
15
  "cii",
16
+ "un-cefact",
17
+ "cross-industry-invoice",
12
18
  "pdf",
19
+ "pdfa",
20
+ "pdf-a",
13
21
  "pdf-a3",
22
+ "pdfa3",
23
+ "xmp",
14
24
  "invoice",
15
25
  "e-invoice",
16
26
  "e-invoicing",
27
+ "einvoice",
28
+ "e-invoice-eu",
29
+ "electronic-invoice",
30
+ "b2g",
17
31
  "eu",
18
- "xml"
32
+ "germany",
33
+ "france",
34
+ "xml",
35
+ "typescript",
36
+ "deno"
19
37
  ],
20
38
  "license": "EUPL-1.2",
21
39
  "author": "StackForge UG",
package/schema/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Factur-X / ZUGFeRD Schema Files
2
2
 
3
- > **Source:** Factur-X 1.08 / ZUGFeRD 2.4 official specifications
4
- > **Reorganized from:** ZF24_EN/Schema
3
+ > **Source:** Factur-X 1.09 / ZUGFeRD 2.5 official specifications (2026-06-10)
4
+ > **Reorganized from:** the official `XSD_SCHEMATRON` distribution (filenames normalized; internal `schemaLocation` references rewritten to match)
5
5
 
6
6
  ---
7
7
 
@@ -26,10 +26,23 @@ The package validates generated XML **against the profile-specific XSD** before
26
26
 
27
27
  ## Version
28
28
 
29
- - **Factur-X:** 1.08
30
- - **ZUGFeRD:** 2.4
29
+ - **Factur-X:** 1.09
30
+ - **ZUGFeRD:** 2.5
31
31
  - **CII:** D22B
32
- - **Effective:** 2026-01-15
32
+ - **Effective:** 2026-05-15 (code lists & validation rules)
33
+
34
+ > Factur-X 1.09 keeps the same CII **D22B** syntax, namespaces, and profile URNs
35
+ > (`urn:factur-x.eu:1p0:*`) as 1.08, so it is fully backward compatible — XML that
36
+ > validates against 1.08 also validates against 1.09. For the MINIMUM, BASIC WL,
37
+ > BASIC, and EN 16931 profiles the XSDs are content-identical to 1.08; the EXTENDED
38
+ > XSD adds only **optional** elements (debited account name, financial adjustment /
39
+ > charges-on-behalf-of-a-third-party, an optional `listID` attribute).
40
+ >
41
+ > The `.sch` (Schematron) and `_codedb.xml` files carry the updated 1.09 code lists
42
+ > and CEN validation rules. They are kept here as reference only — this package
43
+ > performs **XSD validation**, not Schematron validation, and ships only `*.xsd`.
44
+ > The per-profile `Factur-X_1.08_*.xlsx` workbooks are legacy human-reference
45
+ > extracts and are not used at runtime.
33
46
 
34
47
  ---
35
48
 
@@ -16,7 +16,9 @@
16
16
  </xs:simpleType>
17
17
  <xs:complexType name="AllowanceChargeReasonCodeType">
18
18
  <xs:simpleContent>
19
- <xs:extension base="qdt:AllowanceChargeReasonCodeContentType"/>
19
+ <xs:extension base="qdt:AllowanceChargeReasonCodeContentType">
20
+ <xs:attribute name="listID" type="xs:token" default="4465_AllowanceChargeReasonCode"/>
21
+ </xs:extension>
20
22
  </xs:simpleContent>
21
23
  </xs:complexType>
22
24
  <xs:simpleType name="ContactTypeCodeContentType">
@@ -30,6 +30,12 @@
30
30
  <xs:complexType name="DebtorFinancialAccountType">
31
31
  <xs:sequence>
32
32
  <xs:element name="IBANID" type="udt:IDType"/>
33
+ <xs:element name="AccountName" type="udt:TextType" minOccurs="0"/>
34
+ </xs:sequence>
35
+ </xs:complexType>
36
+ <xs:complexType name="DebtorFinancialInstitutionType">
37
+ <xs:sequence>
38
+ <xs:element name="BICID" type="udt:IDType" minOccurs="0"/>
33
39
  </xs:sequence>
34
40
  </xs:complexType>
35
41
  <xs:complexType name="DocumentContextParameterType">
@@ -65,6 +71,12 @@
65
71
  <xs:element name="EffectiveSpecifiedPeriod" type="ram:SpecifiedPeriodType" minOccurs="0"/>
66
72
  </xs:sequence>
67
73
  </xs:complexType>
74
+ <xs:complexType name="FinancialAdjustmentType">
75
+ <xs:sequence>
76
+ <xs:element name="Reason" type="udt:TextType"/>
77
+ <xs:element name="ActualAmount" type="udt:AmountType"/>
78
+ </xs:sequence>
79
+ </xs:complexType>
68
80
  <xs:complexType name="HeaderTradeAgreementType">
69
81
  <xs:sequence>
70
82
  <xs:element name="BuyerReference" type="udt:TextType" minOccurs="0"/>
@@ -116,6 +128,7 @@
116
128
  <xs:element name="SpecifiedLogisticsServiceCharge" type="ram:LogisticsServiceChargeType" minOccurs="0" maxOccurs="unbounded"/>
117
129
  <xs:element name="SpecifiedTradePaymentTerms" type="ram:TradePaymentTermsType" minOccurs="0" maxOccurs="unbounded"/>
118
130
  <xs:element name="SpecifiedTradeSettlementHeaderMonetarySummation" type="ram:TradeSettlementHeaderMonetarySummationType"/>
131
+ <xs:element name="SpecifiedFinancialAdjustment" type="ram:FinancialAdjustmentType" minOccurs="0" maxOccurs="unbounded"/>
119
132
  <xs:element name="InvoiceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
120
133
  <xs:element name="ReceivableSpecifiedTradeAccountingAccount" type="ram:TradeAccountingAccountType" minOccurs="0" maxOccurs="unbounded"/>
121
134
  <xs:element name="SpecifiedAdvancePayment" type="ram:AdvancePaymentType" minOccurs="0" maxOccurs="unbounded"/>
@@ -161,7 +174,7 @@
161
174
  <xs:element name="ApplicableTradeTax" type="ram:TradeTaxType" minOccurs="0" maxOccurs="unbounded"/>
162
175
  <xs:element name="BillingSpecifiedPeriod" type="ram:SpecifiedPeriodType" minOccurs="0"/>
163
176
  <xs:element name="SpecifiedTradeAllowanceCharge" type="ram:TradeAllowanceChargeType" minOccurs="0" maxOccurs="unbounded"/>
164
- <xs:element name="SpecifiedTradeSettlementLineMonetarySummation" type="ram:TradeSettlementLineMonetarySummationType"/>
177
+ <xs:element name="SpecifiedTradeSettlementLineMonetarySummation" type="ram:TradeSettlementLineMonetarySummationType" minOccurs="0"/>
165
178
  <xs:element name="InvoiceReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0"/>
166
179
  <xs:element name="AdditionalReferencedDocument" type="ram:ReferencedDocumentType" minOccurs="0" maxOccurs="unbounded"/>
167
180
  <xs:element name="ReceivableSpecifiedTradeAccountingAccount" type="ram:TradeAccountingAccountType" minOccurs="0" maxOccurs="unbounded"/>
@@ -195,9 +208,9 @@
195
208
  <xs:complexType name="ProductCharacteristicType">
196
209
  <xs:sequence>
197
210
  <xs:element name="TypeCode" type="udt:CodeType" minOccurs="0"/>
198
- <xs:element name="Description" type="udt:TextType"/>
211
+ <xs:element name="Description" type="udt:TextType" minOccurs="0"/>
199
212
  <xs:element name="ValueMeasure" type="udt:MeasureType" minOccurs="0"/>
200
- <xs:element name="Value" type="udt:TextType"/>
213
+ <xs:element name="Value" type="udt:TextType" minOccurs="0"/>
201
214
  </xs:sequence>
202
215
  </xs:complexType>
203
216
  <xs:complexType name="ProductClassificationType">
@@ -409,6 +422,7 @@
409
422
  <xs:element name="DesignatedProductClassification" type="ram:ProductClassificationType" minOccurs="0" maxOccurs="unbounded"/>
410
423
  <xs:element name="IndividualTradeProductInstance" type="ram:TradeProductInstanceType" minOccurs="0" maxOccurs="unbounded"/>
411
424
  <xs:element name="OriginTradeCountry" type="ram:TradeCountryType" minOccurs="0"/>
425
+ <xs:element name="ManufacturerTradeParty" type="ram:TradePartyType" minOccurs="0"/>
412
426
  <xs:element name="IncludedReferencedProduct" type="ram:ReferencedProductType" minOccurs="0" maxOccurs="unbounded"/>
413
427
  </xs:sequence>
414
428
  </xs:complexType>
@@ -433,7 +447,7 @@
433
447
  </xs:complexType>
434
448
  <xs:complexType name="TradeSettlementLineMonetarySummationType">
435
449
  <xs:sequence>
436
- <xs:element name="LineTotalAmount" type="udt:AmountType"/>
450
+ <xs:element name="LineTotalAmount" type="udt:AmountType" minOccurs="0"/>
437
451
  <xs:element name="ChargeTotalAmount" type="udt:AmountType" minOccurs="0"/>
438
452
  <xs:element name="AllowanceTotalAmount" type="udt:AmountType" minOccurs="0"/>
439
453
  <xs:element name="TaxTotalAmount" type="udt:AmountType" minOccurs="0" maxOccurs="2"/>
@@ -448,6 +462,7 @@
448
462
  <xs:element name="ApplicableTradeSettlementFinancialCard" type="ram:TradeSettlementFinancialCardType" minOccurs="0"/>
449
463
  <xs:element name="PayerPartyDebtorFinancialAccount" type="ram:DebtorFinancialAccountType" minOccurs="0"/>
450
464
  <xs:element name="PayeePartyCreditorFinancialAccount" type="ram:CreditorFinancialAccountType" minOccurs="0"/>
465
+ <xs:element name="PayerSpecifiedDebtorFinancialInstitution" type="ram:DebtorFinancialInstitutionType" minOccurs="0"/>
451
466
  <xs:element name="PayeeSpecifiedCreditorFinancialInstitution" type="ram:CreditorFinancialInstitutionType" minOccurs="0"/>
452
467
  </xs:sequence>
453
468
  </xs:complexType>