Skip to content

Add XRechnung structured format reader for inbound e-documents#9690

Open
Groenbech96 wants to merge 3 commits into
mainfrom
copilot/xrechnung-structured-format-reader
Open

Add XRechnung structured format reader for inbound e-documents#9690
Groenbech96 wants to merge 3 commits into
mainfrom
copilot/xrechnung-structured-format-reader

Conversation

@Groenbech96

@Groenbech96 Groenbech96 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a structured format reader for the German XRechnung e-document format so inbound XRechnung XML is parsed directly into the E-Document Purchase draft tables via the IStructuredFormatReader interface — no pre/post Data Exchange field mappings.

Changes

  • E-Document XRechnung Handler codeunit (11039) — implements IStructuredFormatReader, reading UBL Invoice and CreditNote documents into the E-Document Purchase Header (header + lines), with feature telemetry.
  • XRechnung EDoc Read into Draft enum extension — binds the handler to the E-Doc. Read into Draft reader enum.
  • TestsXRechnungStructuredTests and XRechnungStructuredValidations codeunits, plus a sample xrechnung-invoice-0.xml test resource. Registers the test .resources folder and adds the E-Document for Germany Tests dependency to the W1 E-Document test app.

Notes

  • Approach follows the "read straight into the draft tables" direction — the Prepare Draft stage handles vendor/item/account resolution, so no intermediate mapping codeunit is needed.
  • Please rely on CI for full compile + test verification.

Implement IStructuredFormatReader for the German XRechnung format so inbound
XRechnung XML (UBL Invoice and CreditNote) is parsed directly into the
E-Document Purchase draft tables, without pre/post data-exchange mappings.

- Add "E-Document XRechnung Handler" codeunit (11039) implementing
  IStructuredFormatReader for invoice and credit note documents
- Add "XRechnung EDoc Read into Draft" enum extension binding the handler
- Add structured tests, validation helpers, and a sample XRechnung invoice
  test resource; register the test .resources folder and the DE test dependency

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Groenbech96
Groenbech96 requested review from a team July 23, 2026 11:23
@Groenbech96
Groenbech96 requested review from a team as code owners July 23, 2026 11:23
@github-actions github-actions Bot added AL: Apps (W1) Add-on apps for W1 Integration GitHub request for Integration area labels Jul 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Could not find a linked ADO work item. Please link one by using the pattern 'AB#' followed by the relevant work item number. You may use the 'Fixes' keyword to automatically resolve the work item when the pull request is merged. E.g. 'Fixes AB#1234'

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
codeunit 13928 "XRechnung Struct. Validations"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Breaking\ Changes}$

The helper codeunit "XRechnung Struct. Validations" exposes test-only setter procedures (SetMockDate, SetMockCurrencyCode) with default public access even though the diff only uses them from within the same test app. That widens the supported symbol surface unnecessarily; make the helper's cross-codeunit entry points internal.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.14.4

XmlNamespaces.AddNamespace('cn', DefaultCreditNoteTok);

XRechnungXml.GetRoot(XmlElement);
case UpperCase(XmlElement.LocalName()) of

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Error\ Handling}$

ReadIntoDraft switches on XmlElement.LocalName() with no else branch. If an unexpected XML root reaches this reader, the code falls through after inserting the draft header and returns the enum's default value instead of surfacing a clear unsupported-format error; add an else branch that raises a dedicated Error or ErrorInfo before continuing.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.14.4

using Microsoft.eServices.EDocument.Formats;
using Microsoft.eServices.EDocument.Processing.Interfaces;

enumextension 13917 "XRechnung EDoc Read into Draft" extends "E-Doc. Read into Draft"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Interfaces}$

This new enum extension adds a persisted "XRechnung" value to "E-Doc. Read into Draft", but the base enum still relies only on DefaultImplementation and declares no UnknownValueImplementation. If the Germany app is later uninstalled, stored XRechnung ordinals no longer match any declared value, and resolving the enum to IStructuredFormatReader can fail with a technical runtime error instead of controlled handling.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.14.4

XRechnungXml: XmlDocument;
XmlNamespaces: XmlNamespaceManager;
XmlElement: XmlElement;
ProcessDraft: Enum "E-Doc. Process Draft";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style}$

ReadIntoDraft declares six Labels inside its procedure-local var block. Per the referenced guidance, Labels should live in the codeunit's top-level var section so XLIFF extraction and translation review stay stable; move these XML namespace and telemetry Labels out of the procedure scope.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.14.4

FeatureNameTok: Label 'E-document XRechnung Format', Locked = true;
StartEventNameTok: Label 'E-document XRechnung import started. Parsing basic information.', Locked = true;
begin
FeatureTelemetry.LogUsage('0000EXH', FeatureNameTok, StartEventNameTok);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Telemetry}$

FeatureTelemetry.LogUsage is emitted before the handler has parsed the XML or determined whether it can build a draft purchase document, so failed or unsupported XRechnung imports will be counted as successful feature usage. Move the usage event to a confirmed-success path after the draft has been created, and log failures separately if they need telemetry.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.14.4

Codeunit 13927 "XRechnung Structured Tests" (Subtype = Test) lives in the
E-Document for Germany Tests country-specific ID range, consistent with the
app's other test objects (13918, 13922-13926). Add it to the allowed
out-of-range test object exception list so TestObjectIdsAndManifests passes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the Build: Automation Workflows and other setup in .github folder label Jul 23, 2026
FeatureTelemetry.LogUsage('0000EXH', FeatureNameTok, StartEventNameTok);
EDocumentPurchaseHeader.InsertForEDocument(EDocument);

XmlDocument.ReadFrom(TempBlob.CreateInStream(TextEncoding::UTF8), XRechnungXml);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Error\ Handling}$

In codeunit "E-Document XRechnung Handler".ReadIntoDraft, the Boolean result of XmlDocument.ReadFrom(TempBlob.CreateInStream(TextEncoding::UTF8), XRechnungXml) is discarded. If the incoming blob is not well-formed XML, the call fails to populate XRechnungXml but processing continues as if it had succeeded, so XRechnungXml.GetRoot(XmlElement) and everything downstream operate on an empty/undefined document instead of surfacing a clear error to the user. The sibling implementation of the same interface, codeunit "E-Document PINT A-NZ Handler" (src/Apps/APAC/EDocumentFormats/PINT A-NZ/app/src/Core/EDocumentPINTANZHandler.Codeunit.al), guards this exact call with 'if not XmlDocument.ReadFrom(...) then Error(CouldNotParseXmlErr);'. Recommend mirroring that pattern here so a malformed XRechnung payload fails with a clear, actionable error instead of silently producing an incomplete draft.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.15.4

The PR Build TestObjectIdsAndManifests check runs from @main, so adding
13927 to the branch's out-of-range exception list had no effect on the gate
(the exception list is maintained centrally on main). Instead, renumber
codeunit "XRechnung Structured Tests" from 13927 to 148500, inside the
standard 130000..149999 test object range, and declare a 148500..148509
idRange in the E-Document for Germany Tests app. The chosen band avoids the
E-Document Core Tests (139500..139899 / 133501..133509) and Elster test
(148000..148499) allocations in the dependency/localization closure. Revert
the exception-list edit so the central file is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot removed the Build: Automation Workflows and other setup in .github folder label Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1 Integration GitHub request for Integration area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant