Add XRechnung structured format reader for inbound e-documents#9690
Add XRechnung structured format reader for inbound e-documents#9690Groenbech96 wants to merge 3 commits into
Conversation
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>
|
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" |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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"; |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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>
| FeatureTelemetry.LogUsage('0000EXH', FeatureNameTok, StartEventNameTok); | ||
| EDocumentPurchaseHeader.InsertForEDocument(EDocument); | ||
|
|
||
| XmlDocument.ReadFrom(TempBlob.CreateInStream(TextEncoding::UTF8), XRechnungXml); |
There was a problem hiding this comment.
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>
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
IStructuredFormatReaderinterface — no pre/post Data Exchange field mappings.Changes
E-Document XRechnung Handlercodeunit (11039) — implementsIStructuredFormatReader, reading UBLInvoiceandCreditNotedocuments into theE-Document Purchase Header(header + lines), with feature telemetry.XRechnung EDoc Read into Draftenum extension — binds the handler to theE-Doc. Read into Draftreader enum.XRechnungStructuredTestsandXRechnungStructuredValidationscodeunits, plus a samplexrechnung-invoice-0.xmltest resource. Registers the test.resourcesfolder and adds the E-Document for Germany Tests dependency to the W1 E-Document test app.Notes