Skip to content

[E-Document Formats] Fix defects in V2 draft migration for XRechnung, PINT A-NZ and Factura-E - #9784

Merged
Groenbech96 merged 3 commits into
mainfrom
edoc/fix-v2-draft-migration-defects
Jul 29, 2026
Merged

[E-Document Formats] Fix defects in V2 draft migration for XRechnung, PINT A-NZ and Factura-E#9784
Groenbech96 merged 3 commits into
mainfrom
edoc/fix-v2-draft-migration-defects

Conversation

@Groenbech96

@Groenbech96 Groenbech96 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Fixes AB#644279

Summary

Verification of the local e-document formats migrated to the V2 (draft) import pipeline found several defects where the migrated formats deviate from the DK OIOUBL reference implementation. This PR fixes the high-confidence functional defects.

Related migrations: #9426 (PINT A-NZ, Factura-E), #9682 (OIOUBL), #9690 (XRechnung).

Fixes

XRechnung (DE) — EDocumentXRechnungHandler.Codeunit.al

Defect Impact
ResetDraft was never called from ReadIntoDraft Re-running Read into Draft appended a second set of purchase lines, because GetNextLineNo keeps incrementing. ResetDraft was dead code.
ResetDraft used GetFromEDocument + Delete(true) Errors when no draft header exists yet. Now deletes the header/line ranges, matching EDocumentOIOUBLHandler.
Root element case had no else and did not validate the root namespace Unsupported documents (e.g. CII CrossIndustryInvoice) silently produced an empty draft and returned an uninitialised "E-Doc. Process Draft". Now rejected with an error, matching OIOUBL.

PINT A-NZ (APAC)

Defect Impact
GetVendorRelatedData declared VendorParticipantId / VendorName / VendorAddress by value (PINTANZImport.Codeunit.al) The participant-id and name+address vendor-matching fallbacks in TryMatchVendor always received empty strings — dead fallback logic.
Credit notes did not map cac:BillingReference/cac:InvoiceDocumentReference/cbc:ID "Applies-to Ext. Invoice No." stayed empty, so EDocCreatePurchCrMemo could not apply the credit memo to the original invoice. Core PEPPOL and OIOUBL both map this.

Factura-E (ES)

Defect Impact
InvoiceHeader/Corrective/InvoiceNumber mapped to "Purchase Order No." Finish draft treats that field as a vendor order number. Rectificative invoices were never applied to the original invoice. Now mapped to "Applies-to Ext. Invoice No.".

Tests

Added three regression tests to XRechnungStructuredTests.Codeunit.al, mirroring the existing OIOUBL suite:

  • TestXRechnungUnsupportedRootElement_IsRejected
  • TestXRechnungUnexpectedRootNamespace_IsRejected
  • TestXRechnungInvoice_ReadIntoDraftTwice_DoesNotDuplicateLines

Not included (tracked separately)

The following gaps were also identified during verification and are being filed as work items rather than fixed here, since they need schema review and new test fixtures:

  • Tax/VAT totals read from derived arithmetic instead of cac:TaxTotal/cbc:TaxAmount (OIOUBL, PINT A-NZ)
  • Document- and line-level allowances/charges not mapped (all four formats)
  • Embedded attachments (cac:AdditionalDocumentReference) not imported (OIOUBL, PINT A-NZ, Factura-E, XRechnung)
  • Factura-E: invoice-level GeneralDiscounts / line DiscountsAndRebates not mapped; multi-invoice batches merge all lines into one draft
  • XRechnung: CII (UN/CEFACT) syntax not supported; test suite sets up the service with "E-Document Format"::Mock rather than the real format

Reviewer note: Factura-E mapping deliberately diverges from V1

The V1 importer maps Corrective/InvoiceNumber to a different field than this PR does:

Path Corrective/InvoiceNumber target
V1 (FacturaEImport.Codeunit.al:217-218) "Applies-to Doc. No."
V2 before this PR (EDocumentFacturaEHandler.Codeunit.al:116) "Purchase Order No."
V2 after this PR "Applies-to Ext. Invoice No."

EDocCreatePurchCrMemo.Codeunit.al:62-73 treats the two draft fields differently:

  • "Applies-to Doc. No." is used verbatim as a BC posted-invoice number.
  • "Applies-to Ext. Invoice No." is resolved by looking up Purch. Inv. Header."Vendor Invoice No." for the vendor, and only then sets "Applies-to Doc. No.".

On an inbound credit memo, Corrective/InvoiceNumber is the original invoice number as issued by the vendor, not a BC document number. Therefore the resolving field is the correct target, and this matches every other V2 reader:

  • core PEPPOL — EDocumentPEPPOLHandler.Codeunit.al:151-152
  • DK OIOUBL — EDocumentOIOUBLHandler.Codeunit.al:144

V1's direct write to "Applies-to Doc. No." only applies correctly when the vendor's numbering happens to equal BC's posted invoice number; otherwise it fails to apply or mis-applies to an unrelated document. This PR intentionally does not preserve that V1 behavior. Please confirm this is acceptable.

… PINT A-NZ and Factura-E

Verification of the local e-document formats migrated to the V2 (draft) import
pipeline found several defects where the migrated formats deviated from the
OIOUBL reference implementation.

XRechnung (DE):
- ReadIntoDraft never called ResetDraft, so re-running "Read into Draft"
  appended a second set of purchase lines (GetNextLineNo keeps incrementing).
  ResetDraft was effectively dead code.
- ResetDraft used GetFromEDocument + Delete(true), which errors when no draft
  header exists yet. Aligned with the OIOUBL implementation that deletes the
  header and line ranges.
- The root element case had no else branch and did not validate the root
  namespace, so unsupported documents (for example CII CrossIndustryInvoice)
  silently produced an empty draft with an uninitialised process draft enum.
  Unsupported roots and namespaces are now rejected with an error.
- Added regression tests for unsupported root element, unexpected root
  namespace, and re-running Read into Draft.

PINT A-NZ (APAC):
- GetVendorRelatedData declared VendorParticipantId, VendorName and
  VendorAddress by value, so the participant-id and name/address vendor
  matching fallbacks in TryMatchVendor always received empty values.
- Credit notes did not map BillingReference/InvoiceDocumentReference/ID, so
  "Applies-to Ext. Invoice No." stayed empty and finish draft could not apply
  the credit memo to the original invoice.

Factura-E (ES):
- InvoiceHeader/Corrective/InvoiceNumber was mapped to "Purchase Order No."
  instead of "Applies-to Ext. Invoice No.". Finish draft treats the former as
  a vendor order number, so rectificative invoices were never applied to the
  original invoice.

Co-authored-by: Copilot <[email protected]>
@Groenbech96
Groenbech96 requested a review from a team July 28, 2026 09:26
@github-actions github-actions Bot added the Integration GitHub request for Integration area label Jul 28, 2026
@github-actions github-actions Bot added this to the Version 29.0 milestone Jul 28, 2026
Magnus Hartvig Grønbech and others added 2 commits July 28, 2026 12:49
…ests

Resolves 'Build Apps DE' compile failure in Pull Request Build: AL0789 'Using directives are ignored if a namespace is not specified.' in E-Document for Germany Tests. XRechnungStructuredTests.Codeunit.al declares no namespace, so the added using directive is ignored by the compiler; IStructuredFormatReader resolves without it.

[bcapps-fix-loop attempt 1]

Co-authored-by: Copilot <[email protected]>
@Groenbech96
Groenbech96 enabled auto-merge July 29, 2026 05:55
@Groenbech96
Groenbech96 added this pull request to the merge queue Jul 29, 2026
Merged via the queue into main with commit eaf156e Jul 29, 2026
329 of 332 checks passed
@Groenbech96
Groenbech96 deleted the edoc/fix-v2-draft-migration-defects branch July 29, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Integration GitHub request for Integration area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants